[
  {
    "path": ".editorconfig",
    "content": "# top-most EditorConfig file\nroot = true\n\n[*]\nend_of_line = lf\ninsert_final_newline = true\nquote_type = single\n\n# Tab indentation\n[*.{js,ts,jsx,tsx,json}]\nindent_style = space\nindent_size = 2\n\n# Space indentation\n[package.json]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto\n\n*.css text eol=lf\n*.js text eol=lf\n*.jsx text eol=lf\n*.ts text eol=lf linguist-language=JavaScript\n*.tsx text eol=lf linguist-language=JavaScript\n*.json text eol=lf\n*.html text eol=lf\n*.md text eol=lf\n.gitattributes text eol=lf\n"
  },
  {
    "path": ".github/COMMIT_TEMPLATE.md",
    "content": "# <type>: (If applied, this commit will...) <subject> (Max 50 char)\n# |<----  Using a Maximum Of 50 Characters  ---->|\n\n\n# Explain why this change is being made\n# |<----   Try To Limit Each Line to a Maximum Of 72 Characters   ---->|\n\n# Provide links or keys to any relevant tickets, articles or other resources\n# Example: Github issue #23\n\n# --- COMMIT END ---\n# Type can be \n#    feat     (new feature)\n#    fix      (bug fix)\n#    refactor (refactoring production code)\n#    style    (formatting, missing semi colons, etc; no code change)\n#    docs     (changes to documentation)\n#    test     (adding or refactoring tests; no production code change)\n#    chore    (updating grunt tasks etc; no production code change)\n# --------------------\n# Remember to\n#    Capitalize the subject line\n#    Use the imperative mood in the subject line\n#    Do not end the subject line with a period\n#    Separate subject from body with a blank line\n#    Use the body to explain what and why vs. how\n#    Can use multiple lines with \"-\" for bullet points in body\n# --------------------\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\nopen_collective: inferno\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "*Before* submitting an issue please:\n- Check that you are using the latest version of Inferno. Either using our [CDN @ Master](http://cdn.infernojs.org/latest/inferno.js) or by checking the tags on [NPM](http://www.npmjs.com/package/inferno).\n- Check that the bug has not been fixed in the latest development version. Use our [CDN @ Edge](http://cdn.infernojs.org/edge/inferno.js).\n- Check that the issue has not been brought up before on [Github issues](http://www.github.com/infernojs/inferno/issues).\n\n**If you can, please distill your problem down and include a JSFiddle example for illustration. Also when requesting bug fix please include at least one test to avoid regression.**\n---\n\n## Issue Template\n\n**Observed Behaviour**\n\nInferno is...\n\n**Expected Current Behaviour**\n\nInferno should... \n\n**Inferno Metadata**\n\nmacOS / Windowx / Linux\nSafari / Chrome / Firefox / ... \n\n<!-- Love inferno? Please consider supporting our collective:\n👉  https://opencollective.com/inferno/donate -->\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": " *Before* submitting a PR please:\n - Include tests for the functionality you are adding! See CONTRIBUTING.md for details how to run tests.\n - Run `npm run build` and check that the build succeeds.\n - Ensure that the PR hasn't been submitted before.\n\n---\n\n## PR Template\n\n**Objective**\n\nThis PR...\n\n**Closes Issue**\n\nIt closes Issue #...\n"
  },
  {
    "path": ".github/workflows/ci-template.yml",
    "content": "name: CI\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ '**' ]\n\njobs:\n  tests:\n    runs-on: ubuntu-latest\n    name: Tests\n    steps:\n      - uses: actions/checkout@v4\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: latest\n          \n      - name: Install dependencies\n        run: npm ci\n\n      - name: Lint\n        run: npm run lint\n\n      - name: Build\n        run: npm run build\n\n      - name: Test with coverage\n        run: npm run test:coverage\n\n      - name: Upload coverage to Coveralls\n        uses: coverallsapp/github-action@v2\n\n      - name: Run browser tests on SauceLabs\n        run: npm run test:browser:sauce\n        env:\n          SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}\n          SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: \"CodeQL\"\n\non:\n  push:\n    branches: [ \"master\" ]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [ \"master\" ]\n  schedule:\n    - cron: '19 8 * * 0'\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [ 'javascript' ]\n        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]\n        # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support\n\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v3\n\n    # Initializes the CodeQL tools for scanning.\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v2\n      with:\n        languages: ${{ matrix.language }}\n        # If you wish to specify custom queries, you can do so here or in a config file.\n        # By default, queries listed here will override any specified in a config file.\n        # Prefix the list here with \"+\" to use these queries and those in the config file.\n        \n        # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs\n        # queries: security-extended,security-and-quality\n\n        \n    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).\n    # If this step fails, then you should remove it and run the build manually (see below)\n    - name: Autobuild\n      uses: github/codeql-action/autobuild@v2\n\n    # ℹ️ Command-line programs to run using the OS shell.\n    # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun\n\n    #   If the Autobuild fails above, remove it and uncomment the following three lines. \n    #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.\n\n    # - run: |\n    #   echo \"Run, Build Application using script\"\n    #   ./location_of_script_within_repo/buildscript.sh\n\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v2\n"
  },
  {
    "path": ".gitignore",
    "content": ".idea\n.vscode\n\n.DS_Store\n.rpt2_cache*\n.changelog\n\n*.log\n\nbuild\ndist\ncoverage\nnode_modules\nfixtures/browser/*.cmd\n\npackages/*/dist\npackages/*/tmpDist\npackages/*/package-lock.json\n\n.rpt2_cache_development\n.rpt2_cache_production\n\n.swc\n"
  },
  {
    "path": ".npmrc",
    "content": "legacy-peer-deps=true\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "See GitHub for changes https://github.com/infernojs/inferno/releases\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Contributing to Inferno\n==========================\n\nMany thanks for using Inferno and contributing to its development. The following is a quick set of guidelines designed to maximise your contribution's effectiveness.\n\nGot a question or need help?\n----------------------------\n\nIf you're having trouble getting Inferno to do what you want, there are a couple of places to get help before submitting an issue:\n\n* [Stack Overflow questions tagged infernojs](http://stackoverflow.com/questions/tagged/infernojs)\n\nOf course, if you've encountered a bug, then the best course of action is to raise an issue (if no-one else has!).\n\nReporting security vulnerabilities\n----------------------------------\n\nIf you think you've found a security vulnerability, please email [Dominic Gannaway](mailto:dg@domgan.com) with details, and he will respond to you if he isn't at work by that time.\n\nRepository Layout\n-----------------\n\nThe repository structures as a monorepo utilizing [lerna](https://github.com/lerna/lerna) as a management tool of choice. Lerna setup and linking are part of the `postinstall` task so it should be automatically\nrun after `npm install`. `lerna` executes command based on a topological-sorted order of packages based on their dependencies.\n\nFor example, if you want to see the order of packages being processed, you can do:\n```\n$ lerna exec -- node -e \"console.log(require('./package.json').name)\"\ninferno-shared\ninferno-vnode-flags\ninferno\ninferno-hyperscript\ninferno-create-element\ninferno-extras\ninferno-router\ninferno-compat\ninferno-server\ninferno-redux\ninferno-mobx\ninferno-test-utils\n```\n\nSource files are written in TypeScript and tests are written in JS/JSX consuming the dist files.\n\nRunning tests\n-------------\nAlways include tests for the functionality you want to add into Inferno. This way we can avoid regression in future.\n\nMake sure you have lerna tool installed globally.\n\n```\nnpm i -g lerna\n```\n\n- Clone the repository, and clean it. `lerna clean`\n- Install development dependencies `npm i`\n- build typescript files `npm run build`\n- run tests `npm run test`\n\n\nPull requests\n-------------\n\nAll pull requests are welcome.\n\n*Caveat for what follows: If in doubt, submit the request - a PR that needs tweaking is infinitely more valuable than a request that wasn't made because you were worrying about meeting these requirements.*\n\nBefore submitting, run `npm run build` (which will concatenate, lint and test the code) to ensure the build passes - but don't include files from outside the `src` and `test` folders in the PR.\n\nAnd make sure the PR haven't been published before!\n\nThere isn't (yet) a formal style guide for Inferno, so please take care to adhere to existing conventions:\n\n* 2-space indentation, not tabs!\n* Semi-colons\n* Single-quotes for strings\n\nAbove all, code should be clean and readable, and commented where necessary. If you add a new feature, make sure you add a test to go along with it!\n\n\nBefore you commit your changes, please run `npm run prettier` to format code correctly\n\nSmall print\n-----------\n\nThere's no contributor license agreement - contributions are made on a common sense basis. Inferno is distributed under the MIT license, which means your contributions will be too.\n\nDebugging Browser\n-----------------\nJust run `npm run test:browser:debug` Open localhost:9876 and click debug!\n\nDebugging NodeJS\n----------------\nIts possible to debug inferno tests by running following command `npm run debug` and open chrome web address: chrome://inspect/#devices\n\nPro tip: You can filter down number of tests by editing `debug` -task:\n`node --inspect-brk ./node_modules/.bin/jest {*edit this*} --runInBand --no-cache --no-watchman`\nChange parameter to jest to match only files you want to run.\nHappy debugging!\n\n\n## Credits\n\n\n### Contributors\n\nThank you to all the people who have already contributed to inferno!\n<a href=\"graphs/contributors\"><img src=\"https://opencollective.com/inferno/contributors.svg?width=890\" /></a>\n\n\n### Backers\n\nThank you to all our backers! [[Become a backer](https://opencollective.com/inferno#backer)]\n\n<a href=\"https://opencollective.com/inferno#backers\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/backers.svg?width=890\"></a>\n\n\n### Sponsors\n\nThank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/inferno#sponsor))\n\n<a href=\"https://opencollective.com/inferno/sponsor/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/4/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/9/avatar.svg\"></a>\n"
  },
  {
    "path": "LICENSE.md",
    "content": "# MIT License\nCopyright (c) 2015-2022 Dominic Gannaway\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": "README.md",
    "content": "<p align=\"center\"><a href=\"https://infernojs.org/\" target=\"_blank\"><img width=\"150\" alt=\"Inferno\" title=\"Inferno\" src=\"https://user-images.githubusercontent.com/2021355/36063342-626d7ea8-0e84-11e8-84e1-f22bb3b8c4d5.png\"/></a></p>\n\n[![Build Status](https://github.com/infernojs/inferno/workflows/CI/badge.svg)](https://github.com/infernojs/inferno/actions)\n[![Coverage Status](https://img.shields.io/coveralls/infernojs/inferno/master.svg?style=flat-square)](https://coveralls.io/github/infernojs/inferno?branch=master)\n[![MIT](https://img.shields.io/npm/l/inferno.svg?style=flat-square)](https://github.com/infernojs/inferno/blob/master/LICENSE.md)\n[![NPM](https://img.shields.io/npm/v/inferno.svg?style=flat-square)](https://www.npmjs.com/package/inferno)\n[![npm downloads](https://img.shields.io/npm/dm/inferno.svg?style=flat-square)](https://www.npmjs.org/package/inferno)\n[![Discord](https://img.shields.io/discord/825669396823015496.svg?style=flat-square&label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/SUKuhgaBpF)\n[![gzip size](http://img.badgesize.io/https://unpkg.com/inferno/dist/inferno.min.js?compression=gzip)](https://unpkg.com/inferno/dist/inferno.min.js)\n[![Backers on Open Collective](https://opencollective.com/inferno/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/inferno/sponsors/badge.svg)](#sponsors)\n\nInferno is an insanely fast, React-like library for building high-performance user interfaces on both the client and server.\n\n## Description\n\nThe main objective of the InfernoJS project is to provide the fastest possible **runtime** performance for web applications. Inferno excels at rendering real time data views or large DOM trees.\n\nThe performance is achieved through multiple optimizations, for example:\n\n- Inferno's own JSX compilers creates monomorphic `createVNode` calls, instead of `createElement` calls.\nOptimizing runtime performance of the application. \n  - [SWC plugin inferno](https://github.com/infernojs/swc-plugin-inferno) is a plugin for [SWC](https://swc.rs/). It can compile TSX and JSX\n  - [Babel plugin inferno](https://github.com/infernojs/babel-plugin-inferno) is a plugin for [BabelJs](https://babeljs.io/). It can compile JSX.\n  - [TS plugin inferno](https://github.com/infernojs/ts-plugin-inferno) is a plugin for [TSC](https://www.typescriptlang.org/). It can compile TSX.\n- Inferno's diff process uses bitwise flags to memoize the shape of objects\n- Child nodes are normalized only when needed\n- Special JSX flags can be used during compile time to optimize runtime performance at application level\n- Many micro optimizations\n\n## Features\n\n- Component driven + one-way data flow architecture\n- React-like API, concepts and component lifecycle events\n- Partial synthetic event system, normalizing events for better cross browser support\n- Inferno's [`linkEvent`](https://github.com/infernojs/inferno/blob/master/README.md#linkevent-package-inferno) feature removes the need to use arrow functions or binding event callbacks\n- Isomorphic rendering on both client and server with `inferno-server`\n- Unlike React and Preact, Inferno has lifecycle events on functional components\n- Unlike Preact and other React-like libraries, Inferno has controlled components for input/select/textarea elements\n- Components can be rendered outside their current html hierarchy using `createPortal` - API\n- Support for [older browsers](https://github.com/infernojs/inferno#browser-support) without any polyfills\n- defaultHooks for Functional components, this way re-defining lifecycle events per usage can be avoided\n- Inferno supports setting styles using string `<div style=\"background-color: red\"></div>` or using object literal syntax `<div style={{\"background-color\": \"red\"}}></div>`. For camelCase syntax support see [`inferno-compat`](https://github.com/infernojs/inferno/tree/master/packages/inferno-compat).\n- Fragments (v6)\n- createRef and forwardRef APIs (v6)\n- componentDidAppear, componentWillDisappear and componentWillMove (v8) - class and function component callbacks to ease animation work, see [inferno-animation](https://github.com/infernojs/inferno/tree/master/packages/inferno-animation) package\n\n## Runtime requirements\nInferno v9 requires following features to be present in the executing runtime:\n\n- `Promise`\n- `String.prototype.includes()`\n- `String.prototype.startsWith()`\n- `Array.prototype.includes()`\n- `Object.spread()`\n- `for ... of`\n\n## Browser support\nSince version 4 we have started running our test suite **without** any polyfills.\nInferno is now part of [Saucelabs](https://saucelabs.com/) open source program and we use their service for executing the tests.\n\nInfernoJS is actively tested with browsers listed below, however it may run well on older browsers as well.\nThis is due to limited support of browser versions in recent testing frameworks. https://github.com/jasmine/jasmine/blob/main/release_notes/5.0.0.md\n\n[![Browser Test Status](https://app.saucelabs.com/browser-matrix/Havunen.svg)](https://app.saucelabs.com/open_sauce/user/Havunen/tests/vdc)\n\n## Migration guides\n\n- [Inferno v4](https://github.com/infernojs/inferno/blob/master/documentation/v4-migration.md)\n- [Inferno v6](https://github.com/infernojs/inferno/blob/master/documentation/v6-migration.md)\n\n## Benchmarks\n\nLive examples at [https://infernojs.github.io/inferno](https://infernojs.github.io/inferno)\n\n- [UI Bench](https://localvoid.github.io/uibench/)\n- [dbmonster](https://infernojs.github.io/inferno/dbmonster/)\n- [JS Web Frameworks Benchmark (current)](https://krausest.github.io/js-framework-benchmark/current.html)\n- [Isomorphic-UI-Benchmark](https://github.com/marko-js/isomorphic-ui-benchmarks)\n- [1k Components](https://infernojs.github.io/inferno/1kcomponents/)\n\n## Code Example\n\nLet's start with some code. As you can see, Inferno intentionally keeps the same design ideas as React regarding components: one-way data flow and separation of concerns.\n\nIn these examples, JSX is used via the [Inferno JSX Babel Plugin](https://github.com/infernojs/babel-plugin-inferno) to provide a simple way to express Inferno virtual DOM. You do not need to use JSX, it's completely **optional**, you can use [hyperscript](https://github.com/infernojs/inferno/tree/master/packages/inferno-hyperscript) or [createElement](https://github.com/infernojs/inferno/tree/master/packages/inferno-create-element) (like React does).\nKeep in mind that compile time optimizations are available only for JSX.\n\n```jsx\nimport { render } from 'inferno';\n\nconst message = \"Hello world\";\n\nrender(\n  <MyComponent message={ message } />,\n  document.getElementById(\"app\")\n);\n```\nFurthermore, Inferno also uses ES6 components like React:\n\n```jsx\nimport { render, Component } from 'inferno';\n\nclass MyComponent extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      counter: 0\n    };\n  }\n  render() {\n    return (\n      <div>\n        <h1>Header!</h1>\n        <span>Counter is at: { this.state.counter }</span>\n      </div>\n    );\n  }\n}\n\nrender(\n  <MyComponent />,\n  document.getElementById(\"app\")\n);\n```\n\nBecause performance is an important aspect of this library, we want to show you how to optimize your application even further.\nIn the example below we optimize diffing process by using JSX **$HasVNodeChildren** and **$HasTextChildren** to predefine children shape compile time.\nIn the MyComponent render method there is a div that contains JSX expression `node` as its content. Due to dynamic nature of Javascript\nthat variable `node` could be anything and Inferno needs to go through the normalization process to make sure there are no nested arrays or other invalid data.\nInferno offers a feature called ChildFlags for application developers to pre-define the shape of vNode's child node. In this example case\nit is using `$HasVNodeChildren` to tell the JSX compiler, that this vNode contains only single element or component vNode.\nNow inferno will not go into the normalization process runtime, but trusts the developer decision about the shape of the object and correctness of data.\nIf this contract is not kept and `node` variable contains invalid value for the pre-defined shape (fe. `null`), then application would crash runtime.\nThere is also span-element in the same render method, which content is set dynamically through `_getText()` method. There `$HasTextChildren` child-flag\nfits nicely, because the content of that given \"span\" is never anything else than text.\nAll the available child flags are documented [here](https://infernojs.org/docs/guides/optimizations).\n\n```jsx\nimport { createTextVNode, render, Component } from 'inferno';\n\nclass MyComponent extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      counter: 0\n    };\n  }\n\n  _getText() {\n     return 'Hello!';\n  }\n  \n  render() {\n    const node = this.state.counter > 0 ? <div>0</div> : <span $HasTextChildren>{this._getText()}</span>;\n      \n    return (\n      <div>\n        <h1>Header!</h1>\n        <div $HasVNodeChildren>{node}</div>\n      </div>\n    );\n  }\n}\n\nrender(\n  <MyComponent />,\n  document.getElementById(\"app\")\n);\n```\n\n### Tear down\n\nTo tear down inferno application you need to render null on root element. \nRendering `null` will trigger unmount lifecycle hooks for whole vDOM tree and remove global event listeners.\nIt is important to unmount unused vNode trees to free browser memory. \n\n```jsx\nimport { createTextVNode, render, Component } from 'inferno';\n\nconst rootElement = document.getElementById(\"app\");\n\n// Start the application\nrender(\n  <ExampleComponent/>,\n  rootElement\n);\n\n// Tear down\nrender(\n  null,\n  rootElement\n);\n\n```\n\n\n### More Examples\n\nIf you have built something using Inferno you can add them here:\n\n- [**Simple Clock** (@JSFiddle)](https://jsfiddle.net/4bha7kcg/)\n- [**Simple JS Counter** (@github/scorsi)](https://github.com/scorsi/simple-counter-inferno-cerebral-fusebox): SSR Inferno (view) + Cerebral (state manager) + FuseBox (build system/bundler)\n- [**Online interface to TMDb movie database** (@codesandbox.io)](https://codesandbox.io/s/9zjo5yx8po): Inferno + [Inferno hyperscript](https://github.com/infernojs/inferno) (view) + [Superagent](https://github.com/visionmedia/superagent) (network requests) + Web component ([custom elements v1](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements)) + [state-transducer](https://github.com/brucou/state-transducer) \n(state machine library) \n- [**Lemmy - a self-hostable reddit alternative** (front end in Inferno)](https://github.com/dessalines/lemmy)\n\n## Getting Started\n\nThe easiest way to get started with Inferno is by using [Create Inferno App](https://github.com/infernojs/create-inferno-app).\n\nAlternatively, you can try any of the following:\n* the [Inferno Boilerplate](https://github.com/infernojs/inferno-boilerplate) for a very simple setup.\n* for a more advanced example demonstrating how Inferno might be used, we recommend trying out [Inferno Starter Project](https://github.com/nightwolfz/inferno-starter) by [nightwolfz](https://github.com/nightwolfz/).\n* for using Inferno to build a mobile app, try [Inferno Mobile Starter Project](https://github.com/Rudy-Zidan/inferno-mobile) by [Rudy-Zidan](https://github.com/Rudy-Zidan).\n* for [TypeScript](https://www.typescriptlang.org/) support and bundling, check out [ts-plugin-inferno](https://github.com/infernojs/ts-plugin-inferno), or [inferno-typescript-example](https://github.com/infernojs/inferno-typescript-example).\n* for an example of how to use Inferno in [codesandbox](https://codesandbox.io/): https://codesandbox.io/s/znmyj24w4p\n* for using [parcel and typescript](https://github.com/jayy-lmao/inferno-parcel-ts)\n\nCore package:\n\n```sh\nnpm install --save inferno\n```\n\nAddons:\n\n```sh\n# server-side rendering\nnpm install --save inferno-server\n# routing\nnpm install --save inferno-router\n```\n\nPre-bundled files for browser consumption can be found on [our cdnjs](https://cdnjs.com/libraries/inferno):\n\nOr on jsDelivr:\n\n```\nhttps://cdn.jsdelivr.net/npm/inferno@latest/dist/inferno.min.js\n```\n\nOr on unpkg.com:\n\n```\nhttps://unpkg.com/inferno@latest/dist/inferno.min.js\n```\n\n### Creating Virtual DOM\n\n#### JSX:\n```sh\nnpm install --save-dev babel-plugin-inferno\n```\n\n#### Hyperscript:\n```sh\nnpm install --save inferno-hyperscript\n```\n\n#### createElement:\n```sh\nnpm install --save inferno-create-element\n```\n\n### Compatibility with existing React apps\n```sh\nnpm install --save-dev inferno-compat\n```\n\nNote: Make sure you read more about [`inferno-compat`](https://github.com/infernojs/inferno/tree/master/packages/inferno-compat) before using it.\n\n## Third-party state libraries\n\nInferno now has bindings available for some of the major state management libraries out there:\n\n- Redux via [`inferno-redux`](https://github.com/infernojs/inferno/tree/dev/packages/inferno-redux)\n- MobX via [`inferno-mobx`](https://github.com/infernojs/inferno/tree/dev/packages/inferno-mobx)\n- Cerebral via [`@cerebral/inferno`](https://github.com/cerebral/cerebral/tree/master/packages/node_modules/@cerebral/inferno)\n\n## JSX\n\nInferno has its own [JSX Babel plugin](https://github.com/trueadm/babel-plugin-inferno).\n\n## Differences from React\n\n- Inferno doesn't have a fully synthetic event system like React does. Inferno has a partially synthetic event system, instead opting to only delegate certain events (such as `onClick`).\n- Inferno doesn't support React Native. Inferno was only designed for the browser/server with the DOM in mind.\n- Inferno doesn't support legacy string refs, use `createRef` or callback `ref` API\n- Inferno provides lifecycle events on functional components. This is a major win for people who prefer lightweight components rather than ES2015 classes.\n\n## Differences from Preact\n\n- Inferno has a partial synthetic event system, resulting in better performance via delegation of certain events.\n- Inferno is *much* faster than Preact in rendering, updating and removing elements from the DOM. Inferno diffs against virtual DOM, rather than the real DOM (except when loading from server-side rendered content), which means it can make drastic improvements. Unfortunately, diffing against the real DOM has a 30-40% overhead cost in operations.\n- Inferno fully supports controlled components for `input`/`select`/`textarea` elements. This prevents lots of edgecases where the virtual DOM is not the source of truth (it should always be). Preact pushes the source of truth to the DOM itself.\n- Inferno provides lifecycle events on functional components. This is a major win for people who prefer lightweight components rather than ES2015 classes.\n\n## Event System\n\nLike React, Inferno also uses a light-weight synthetic event system in certain places (although both event systems differ massively). Inferno's event system provides highly efficient delegation and an event helper called [`linkEvent`](https://github.com/infernojs/inferno/blob/master/README.md#linkevent-package-inferno).\n\nOne major difference between Inferno and React is that Inferno does not rename events or change how they work by default. Inferno only specifies that events should be camel cased, rather than lower case. Lower case events will bypass\nInferno's event system in favour of using the native event system supplied by the browser. For example, when detecting changes on an `<input>` element, in React you'd use `onChange`, with Inferno you'd use `onInput` instead (the\nnative DOM event is `oninput`).\n\nAvailable synthetic events are:\n- `onClick`\n- `onDblClick`\n- `onFocusIn`\n- `onFocusOut`\n- `onKeyDown`\n- `onKeyPress`\n- `onKeyUp`\n- `onMouseDown`\n- `onMouseMove`\n- `onMouseUp`\n- `onTouchEnd`\n- `onTouchMove`\n- `onTouchStart`\n\n### `linkEvent` (package: `inferno`)\n\n`linkEvent()` is a helper function that allows attachment of `props`/`state`/`context` or other data to events without needing to `bind()` them or use arrow functions/closures. This is extremely useful when dealing with events in functional components. Below is an example:\n\n```jsx\nimport { linkEvent } from 'inferno';\n\nfunction handleClick(props, event) {\n  props.validateValue(event.target.value);\n}\n\nfunction MyComponent(props) {\n  return <div><input type=\"text\" onClick={ linkEvent(props, handleClick) } /><div>;\n}\n```\n\nThis is an example of using it with ES2015 classes:\n\n\n```jsx\nimport { linkEvent, Component } from 'inferno';\n\nfunction handleClick(instance, event) {\n  instance.setState({ data: event.target.value });\n}\n\nclass MyComponent extends Component {\n  render () {\n    return <div><input type=\"text\" onClick={ linkEvent(this, handleClick) } /><div>;\n  }\n}\n```\n\n`linkEvent()` offers better performance than binding an event in a class constructor and using arrow functions, so use it where possible.\n\n\n## Controlled Components\n\nIn HTML, form elements such as `<input>`, `<textarea>`, and `<select>` typically maintain their own state and update it based on user input.\nIn Inferno, mutable state is typically kept in the state property of components, and only updated with `setState()`.\n\nWe can combine the two by making the Inferno state be the \"single source of truth\". Then the Inferno component that renders a form also\ncontrols what happens in that form on subsequent user input. An input form element whose value is controlled by\nInferno in this way is called a \"controlled component\".\n\n## Inferno Top-Level API\n\n### `render` (package: `inferno`)\n\n```javascript\nimport { render } from 'inferno';\n\nrender(<div />, document.getElementById(\"app\"));\n```\n\nRender a virtual node into the DOM in the supplied container given the supplied virtual DOM. If the virtual node was previously rendered\ninto the container, this will perform an update on it and only mutate the DOM as necessary, to reflect the latest Inferno virtual node.\n\nWarning: If the container element is not empty before rendering, the content of the container will be overwritten on the initial render.\n\n### `createRenderer` (package: `inferno`)\n\n`createRenderer` creates an alternative render function with a signature matching that of the first argument passed to a reduce/scan function. This allows for easier integration with reactive programming libraries, like [RxJS](https://github.com/ReactiveX/rxjs) and [Most](https://github.com/cujojs/most).\n\n```javascript\nimport { createRenderer } from 'inferno';\nimport { scan, map } from 'most';\n\nconst renderer = createRenderer();\n\n\n// NOTE: vNodes$ represents a stream of virtual DOM node updates\nscan(renderer, document.getElementById(\"app\"), vNodes$);\n```\n\nSee [inferno-most-fp-demo](https://github.com/joshburgess/inferno-most-fp-demo) for an example of how to build an app architecture around this.\n\n### `createElement` (package: `inferno-create-element`)\n\nCreates an Inferno VNode using a similar API to that found with React's `createElement()`\n\n```javascript\nimport { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\nclass BasicComponent extends Component {\n  render() {\n    return createElement('div', {\n        className: 'basic'\n      },\n      createElement('span', {\n        className: this.props.name\n      }, 'The title is ', this.props.title)\n    )\n  }\n}\n\nrender(\n  createElement(BasicComponent, { title: 'abc' }),\n  document.getElementById(\"app\")\n);\n```\n\n### `Component` (package: `inferno`)\n\n**Class component:**\n\n```javascript\nimport { Component } from 'inferno';\n\nclass MyComponent extends Component {\n  render() {\n      return <div>My Component</div>\n  }\n}\n```\n\nThis is the base class for Inferno Components when they're defined using ES6 classes.\n\n**Functional component:**\n\n```javascript\nconst MyComponent = ({ name, age }) => (\n  <span>My name is: { name } and my age is: {age}</span>\n);\n```\n\nAnother way of using defaultHooks.\n```javascript\nexport function Static() {\n    return <div>1</div>;\n}\n\nStatic.defaultHooks = {\n    onComponentShouldUpdate() {\n        return false;\n    }\n};\n```\n\nDefault props\n```jsx\nexport function MyFunctionalComponent({value}) {\n    return <div>{value}</div>;\n}\n\nMyFunctionalComponent.defaultProps = {\n    value: 10\n};\n\n```\n\nFunctional components are first-class functions where their first argument is the `props` passed through from their parent.\n\n### `createVNode` (package: `inferno`)\n```js\nimport { createVNode } from 'inferno';\n\ncreateVNode(\n  flags,\n  type,\n  [className],\n  [...children],\n  [childFlags],\n  [props],\n  [key],\n  [ref]\n)\n```\n\ncreateVNode is used to create html element's virtual node object. Typically `createElement()` (package: `inferno-create-element`), `h()` (package: `inferno-hyperscript`) or JSX are used to create\n`VNode`s for Inferno, but under the hood they all use `createVNode()`. Below is an example of `createVNode` usage:\n\n```javascript\nimport { VNodeFlags, ChildFlags } from 'inferno-vnode-flags';\nimport { createVNode, createTextVNode, render } from 'inferno';\n\nconst vNode = createVNode(VNodeFlags.HtmlElement, 'div', 'example', createTextVNode('Hello world!'), ChildFlags.HasVNodeChildren);\n\n// <div class=\"example\">Hello world!</div>\n\nrender(vNode, container);\n```\n\n`createVNode` arguments explained:\n\n`flags`: (number) is a value from [`VNodeFlags`](https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags), this is a numerical value that tells Inferno what the VNode describes on the page.\n\n`type`: (string) is tagName for element for example 'div'\n\n`className`: (string) is the class attribute ( it is separated from props because it is the most commonly used property )\n\n`children`: (vNode[]|vNode) is one or array of vNodes to be added as children for this vNode\n\n`childFlags`: (number) is a value from [`ChildFlags`](https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags), this tells inferno shape of the children so normalization process can be skipped.\n\n`props`: (Object) is object containing all other properties. fe: `{onClick: method, 'data-attribute': 'Hello Community!}`\n\n`key`: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.\n\n`ref`: (function) callback which is called when DOM node is added/removed from DOM.\n\n\n### `createComponentVNode` (package: 'inferno')\n```js\nimport { createComponentVNode } from 'inferno';\n\ncreateComponentVNode(\n  flags,\n  type,\n  [props],\n  [key],\n  [ref]\n)\n```\n\ncreateComponentVNode is used for creating vNode for Class/Functional Component.\n\nExample:\n```javascript\nimport { VNodeFlags, ChildFlags } from 'inferno-vnode-flags';\nimport { createVNode, createTextVNode, createComponentVNode, render } from 'inferno';\n\nfunction MyComponent(props, context) {\n  return createVNode(VNodeFlags.HtmlElement, 'div', 'example', createTextVNode(props.greeting), ChildFlags.HasVNodeChildren);\n}\n\nconst vNode = createComponentVNode(VNodeFlags.ComponentFunction, MyComponent, {\n  greeting: 'Hello Community!'\n}, null, {\n  onComponentDidMount() {\n    console.log(\"example of did mount hook!\")\n  }\n})\n\n// <div class=\"example\">Hello Community!</div>\n\nrender(vNode, container);\n```\n\n\n`createComponentVNode` arguments explained:\n\n`flags`: (number) is a value from [`VNodeFlags`](https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags), this is a numerical value that tells Inferno what the VNode describes on the page.\n\n`type`: (Function/Class) is the class or function prototype for Component\n\n`props`: (Object) properties passed to Component, can be anything\n\n`key`: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.\n\n`ref`: (Function|Object) this property is object for Functional Components defining all its lifecycle methods. For class Components this is function callback for ref.\n\n\n\n### `createTextVNode` (package: 'inferno')\n\ncreateTextVNode is used for creating vNode for text nodes.\n\n`createTextVNode` arguments explained:\ntext: (string) is a value for text node to be created.\nkey: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.\n\n```js\nimport { createTextVNode } from 'inferno';\n\ncreateTextVNode(\n  text,\n  key\n)\n```\n\n\n### `cloneVNode` (package: `inferno-clone-vnode`)\n\nThis package has same API as React.cloneElement\n\n```javascript\nimport { cloneVNode } from 'inferno-clone-vnode';\n\ncloneVNode(\n  vNode,\n  [props],\n  [...children]\n)\n```\n\nClone and return a new Inferno `VNode` using a `VNode` as the starting point. The resulting `VNode` will have the original `VNode`'s props with the new props merged in shallowly. New children will replace existing children. key and ref from the original `VNode` will be preserved.\n\n`cloneVNode()` is almost equivalent to:\n```jsx\n<VNode.type {...VNode.props} {...props}>{children}</VNode.type>\n```\n\nAn example of using `cloneVNode`:\n\n```javascript\nimport { createVNode, render } from 'inferno';\nimport { cloneVNode } from 'inferno-clone-vnode';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nconst vNode = createVNode(VNodeFlags.HtmlElement, 'div', 'example', 'Hello world!');\nconst newVNode = cloneVNode(vNode, { id: 'new' }); // we are adding an id prop to the VNode\n\nrender(newVNode, container);\n```\n\nIf you're using JSX:\n\n```jsx\nimport { render } from 'inferno';\nimport { cloneVNode } from 'inferno-clone-vnode';\n\nconst vNode = <div className=\"example\">Hello world</div>;\nconst newVNode = cloneVNode(vNode, { id: 'new' }); // we are adding an id prop to the VNode\n\nrender(newVNode, container);\n```\n\n### `createPortal` (package: 'inferno')\n\nHTML:\n```html\n<div id=\"root\"></div>\n<div id=\"outside\"></div>\n```\n\nJavascript:\n```jsx\nconst { render, Component, version, createPortal } from 'inferno';\n\nfunction Outsider(props) {\n\treturn <div>{`Hello ${props.name}!`}</div>;\n}\n\nconst outsideDiv = document.getElementById('outside');\nconst rootDiv = document.getElementById('root');\n\nfunction App() {\n\treturn (\n  \t    <div>\n    \t    Main view\n            ...\n            {createPortal(<Outsider name=\"Inferno\" />, outsideDiv)}\n        </div>\n    );\n}\n\n\n// render an instance of Clock into <body>:\nrender(<App />, rootDiv);\n```\n\nResults into:\n```html\n<div id=\"root\">\n    <div>Main view ...</div>\n</div>\n<div id=\"outside\">\n    <div>Hello Inferno!</div>\n</div>\n```\nCool, huh? Updates (props/context) will flow into \"Outsider\" component from the App component the same way as any other Component.\nFor inspiration on how to use it click [here](https://hackernoon.com/using-a-react-16-portal-to-do-something-cool-2a2d627b0202)!\n\n### `createRef` (package: `inferno`)\n\ncreateRef API provides shorter syntax than callback ref when timing of element is not needed.\n\n```jsx\nimport { Component, render, createRef } from 'inferno';\n\nclass Foobar extends Component {\n  constructor(props) {\n    super(props);\n\n    // Store reference somewhere\n    this.element = createRef(); // Returns object {current: null}\n  }\n\n  render() {\n    return (\n      <div>\n        <span id=\"span\" ref={this.element}>\n          Ok\n        </span>\n      </div>\n    );\n  }\n}\n\nrender(<Foobar />, container);\n```\n\n\n### `createFragment` (package: `inferno`)\n\ncreateFragment is the native way to createFragment vNode. `createFragment(children: any, childFlags: ChildFlags, key?: string | number | null)`\n\n`createFragment` arguments explained:\n\n`children`: (Array) Content of fragment vNode, typically array of VNodes\n\n`childFlags`: (number) is a value from [`ChildFlags`](https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags), this tells inferno shape of the children so normalization process can be skipped.\n\n`key`: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.\n\n\nAlternative ways to create fragment vNode are:\n\n- Using JSX `<> ... </>`, `<Fragment> .... </Fragment>` or `<Inferno.Fragment> ... </Inferno.Fragment>`\n- Using createElement API `createElement(Inferno.Fragment, {key: 'test'}, ...children)`\n- Using hyperscript API `h(Inferno.Fragment, {key: 'test'}, children)`\n\n\nIn the below example both fragments are identical except they have different key\n```jsx\nimport { Fragment, render, createFragment } from 'inferno';\nimport { ChildFlags } from 'inferno-vnode-flags';\n\nfunction Foobar() {\n    return (\n      <div $HasKeyedChildren>\n        {createFragment(\n            [<div>Ok</div>, <span>1</span>],\n            ChildFlags.HasNonKeyedChildren,\n            'key1'\n        )}\n        <Fragment key=\"key2\">\n          <div>Ok</div>\n          <span>1</span>\n        </Fragment>\n      </div>\n    );\n}\n\nrender(<Foobar />, container);\n```\n\n\n### `forwardRef` (package: `inferno`)\n\nforwardRef is a new mechanism to \"forward\" ref inside a functional Component.\nIt can be useful if you have simple functional Components and you want to create reference to a specific element inside it.\n\n```jsx\nimport { forwardRef, Component, render } from 'inferno';\n\nconst FancyButton = forwardRef((props, ref) => (\n  <button ref={ref} className=\"FancyButton\">\n    {props.children}\n  </button>\n));\n\nclass Hello extends Component {\n  render() {\n    return (\n      <FancyButton\n        ref={btn => {\n          if (btn) {\n            // btn variable is the button rendered from FancyButton\n          }\n        }}\n      >\n        Click me!\n      </FancyButton>\n    );\n  }\n}\n\nrender(<Hello />, container);\n```\n\n### `hydrate` (package: `inferno-hydrate`)\n\n```javascript\nimport { hydrate } from 'inferno-hydrate';\n\nhydrate(<div />, document.getElementById(\"app\"));\n```\n\nSame as `render()`, but is used to hydrate a container whose HTML contents were rendered by `inferno-server`. Inferno will attempt to attach event listeners to the existing markup.\n\n### `findDOMNode` (package: `inferno-extras`)\nThis feature has been moved from inferno to inferno-compat in v6. No options are needed anymore.\n\nNote: we recommend using a `ref` callback on a component to find its instance, rather than using `findDOMNode()`. `findDOMNode()` cannot be used on functional components.\n\nIf a component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements.\nIn most cases, you can attach a ref to the DOM node and avoid using `findDOMNode()` at all. When render returns null or false, `findDOMNode()` returns null.\nIf Component has rendered fragment it returns the first element.\n\n### Inferno Flags (package: inferno-vnode-flags)\n\n**VNodeFlags:**\n- `VNodeFlags.HtmlElement`\n- `VNodeFlags.ComponentUnknown`\n- `VNodeFlags.ComponentClass`\n- `VNodeFlags.ComponentFunction`\n- `VNodeFlags.Text`\n- `VNodeFlags.SvgElement`\n- `VNodeFlags.InputElement`\n- `VNodeFlags.TextareaElement`\n- `VNodeFlags.SelectElement`\n- `VNodeFlags.Portal`\n- `VNodeFlags.ReCreate` (JSX **$ReCreate**) always re-creates the vNode\n- `VNodeFlags.ContentEditable`\n- `VNodeFlags.Fragment`\n- `VNodeFlags.InUse`\n- `VnodeFlags.ForwardRef`\n- `VNodeFlags.Normalized`\n\n**VNodeFlags Masks:**\n- `VNodeFlags.ForwardRefComponent` Functional component wrapped in forward ref\n- `VNodeFlags.FormElement` - Is form element\n- `VNodeFlags.Element` - Is vNode element\n- `VNodeFlags.Component` - Is vNode Component\n- `VNodeFlags.DOMRef` - Bit set when vNode holds DOM reference\n- `VNodeFlags.InUseOrNormalized` - VNode is used somewhere else or came from normalization process\n- `VNodeFlags.ClearInUseNormalized` - Opposite mask of InUse or Normalized\n\n\n**ChildFlags**\n- `ChildFlags.UnknownChildren` needs Normalization\n- `ChildFlags.HasInvalidChildren` is invalid (null, undefined, false, true)\n- `ChildFlags.HasVNodeChildren` (JSX **$HasVNodeChildren**) is single vNode (Element/Component)\n- `ChildFlags.HasNonKeyedChildren` (JSX **$HasNonKeyedChildren**) is Array of vNodes non keyed (no nesting, no holes)\n- `ChildFlags.HasKeyedChildren` (JSX **$HasKeyedChildren**) is Array of vNodes keyed (no nesting, no holes)\n- `ChildFlags.HasTextChildren` (JSX **$HasTextChildren**) vNode contains only text\n\n**ChildFlags Masks**\n- `ChildFlags.MultipleChildren` Is Array\n\n\n### `renderToString` (package: `inferno-server`)\n\n```javascript\nimport { renderToString } from 'inferno-server';\n\nconst string = renderToString(<div />);\n```\n\nRender a virtual node into an HTML string, given the supplied virtual DOM.\n\n## Functional component lifecycle events\n\n| Name                        | Triggered when                                                  | Arguments to callback           |\n| -----------                 | --------------                                                  | -----------------------         |\n| `onComponentWillMount`      | a functional component is about to mount                        |                                 |\n| `onComponentDidMount`       | a functional component has mounted successfully                 | `domNode`                       |\n| `onComponentShouldUpdate`   | a functional component has been triggered to update             | `lastProps, nextProps`          |\n| `onComponentWillUpdate`     | a functional component is about to perform an update            | `lastProps, nextProps`          |\n| `onComponentDidUpdate`      | a functional component has performed an update                  | `lastProps, nextProps`          |\n| `onComponentWillUnmount`    | a functional component is about to be unmounted                 | `domNode`                       |\n| `onComponentDidAppear`      | a functional component has mounted and is ready for animations  | `domNode, props`                |\n| `onComponentWillDisappear`  | a functional component is unmounted before DOM node is removed  | `domNode, props, callback`      |\n\nonComponentWillDisappear has special type of argument \"callback\" which needs to be called when component is ready to be removed from the DOM. fe. after animations are finished.\n\n## Class component lifecycle events\n\nAll these Component lifecycle methods ( including `render` and `setState - callback`) are called with Component instance context. You don't need to \"bind\" these methods.\n\n| Name                              | Triggered when                                                                        | Arguments to callback           |\n| -----------                       | --------------                                                                        | -----------------------         |\n| `componentDidMount`               | component has been mounted successfully                                                |                                 |\n| `componentWillMount`              | component is about to mount                                                           |                                 |\n| `componentWillReceiveProps`       | before render when component updates                                                  | `nextProps, context`            |\n| `shouldComponentUpdate`           | component has been triggered to update                                                | `nextProps, nextState`          |\n| `componentWillUpdate`             | component is about to perform an update                                               | `nextProps, nextState, context` |\n| `componentDidUpdate`              | component has performed an update                                                     | `lastProps, lastState, snapshot`|\n| `componentWillUnmount`            | component is about to be unmounted                                                    |                                 |\n| `getChildContext`                 | before render method, return value object is combined to sub tree context             |                                 |\n| `getSnapshotBeforeUpdate`         | before component updates, return value is sent to componentDidUpdate as 3rd parameter | `lastProps, lastState`          |\n| `static getDerivedStateFromProps` | before render method                                                                  | `nextProps, state`              |\n| `componentDidAppear`              | component has mounted and is ready for animations                                     | `domNode`                       |\n| `componentWillDisappear`          | component is unmounted before DOM node is removed                                     | `domNode, callback`             |\n\ncomponentWillDisappear has special type of argument \"callback\" which needs to be called when component is ready to be removed from the DOM. fe. after animations are finished.\n\n### Using functional lifecycle events\n\nFunctional lifecycle events must be explicitly assigned via props onto a functional component like shown below:\n\n```javascript\nimport { render } from 'inferno';\n\nfunction mounted(domNode) {\n  // [domNode] will be available for DOM nodes and components (if the component has mounted to the DOM)\n}\n\nfunction FunctionalComponent({ props }) {\n  return <div>Hello world</div>;\n}\n\nrender(\n  <FunctionalComponent onComponentDidMount={ mounted } />,\n  document.getElementById(\"app\")\n);\n```\n\nPlease note: class components (ES2015 classes) from `inferno` **do not** support the same lifecycle events (they have their own lifecycle events that work as methods on the class itself).\n\n## Development vs Production modes\n\nBy default, Inferno will run in development mode. Development mode provides extra checks and better error messages at the cost of slower performance and larger code to parse.\nWhen using Inferno in a production environment, it is highly recommended that you turn off development mode.\n\n### Running Inferno on Node JS\n\nEnsure the environment variable `process.env.NODE_ENV` is set to `production`.\n\n## Application bundling\n\nWhen building your application bundle, ensure `process.env.NODE_ENV` is replaced with string`\"development\"` or `\"production\"` based on the workflow.\nIt is recommended to use [ts-plugin-inferno](https://github.com/infernojs/ts-plugin-inferno) for typescript TSX compilation and [babel-plugin-infeno](https://github.com/infernojs/babel-plugin-inferno) for javascript JSX compilation.\n\nWhen building for development, you may want to use `inferno.dev.mjs` for v9 or newer and `inferno.dev.esm.js` for older than v9. That bundle file contains ES6 exports for better tree-shaking support, improved error messages and added validation to help fixing possible issues during development.\nThe file is found from `package.json` - `dev:module` entry point and the files are physically located in `node_modules/inferno/dist/` folder.\nRemember that it is not recommended to use that file in production due to slower performance. For production usage use `node_modules/inferno/dist/inferno.mjs` -file for v9 or newer and `node_modules/inferno/dist/inferno.esm.js` -file for older than v9.\n\nExample of **Webpack** configuration:\n\n```js\nconst path = require('path');\nconst infernoTsx = require('ts-plugin-inferno').default;\n\n... webpack config ...\n\n    module: {\n        rules: [\n            {\n                test: /\\.js$/, // Add \"jsx\" if your application uses `jsx` file extensions\n                exclude: /node_modules/,\n                use: [{\n                    loader: 'babel-loader',\n                    options: {\n                        plugins: [\n                            // Compile javascript JSX syntax using inferno's own plugin\n                            ['babel-plugin-inferno', {imports: true}]\n                        ]\n                    }\n                }]\n            },\n            {\n                test: /\\.ts+(|x)$/, // Compile ts and tsx extensions\n                exclude: /node_modules/,\n                use: [{\n                    loader: 'ts-loader',\n                    options: {\n                        getCustomTransformers: () => ({\n                            // inferno custom TSX plugin\n                            after: [infernoTsx()]\n                        }),\n                        compilerOptions: {\n                            /* typescript compiler options */\n                        }\n                    }\n                }]\n            }\n        ]\n    },\n    resolve: {\n        extensions: ['.js', '.ts', '.tsx'],\n        alias: {\n            // This maps import \"inferno\" to es6 module entry based on workflow\n            inferno: path.resolve(__dirname, 'node_modules/inferno/dist', isProduction ? 'index.dev.mjs' : 'index.mjs')\n        }\n    },\n    plugins: [\n        new webpack.DefinePlugin({\n            'process.env': {\n                'NODE_ENV':  JSON.stringify(isProduction ? 'production' : 'development')\n            }\n        })\n    ]\n```\n\nExample of **Rollup** configuration:\n\n```js\nconst path = require('path');\nconst alias = require('@rollup/plugin-alias');\nconst {babel} = require('@rollup/plugin-babel');\nconst replace = require('@rollup/plugin-replace');\nconst typescript = require('rollup-plugin-typescript2');\nconst transformInferno = require('ts-plugin-inferno').default;\n\n... Rollup config ...\n{\n    input: /* entry file */,\n    plugins: [\n            alias({\n                resolve: ['.js'],\n                entries: [\n                    // This maps import \"inferno\" to es6 module entry based on workflow\n                    {find: 'inferno', replacement: path.resolve(__dirname, 'node_modules/inferno/dist', isProduction ? 'index.dev.mjs' : 'index.mjs')}\n                ]\n            }),\n            typescript({\n                include: ['*.ts+(|x)', '**/*.ts+(|x)'],\n                transformers: [\n                    () => ({\n                        after: [transformInferno()]\n                    })\n                ],\n                tsconfig: 'tsconfig.json',\n                tsconfigOverride: {\n                    /* typescript compiler options */\n                }\n            }),\n            babel({\n                babelrc: false,\n                sourceMaps: isDeploy,\n                plugins: [\n                    // Compile javascript JSX syntax using inferno's own plugin\n                    ['babel-plugin-inferno', {imports: true}]\n                ],\n                babelHelpers: 'bundled'\n            })\n    ]\n}\n```\n\n### Custom namespaces\n\nInferno always wants to deliver great performance. In order to do so, it has to make intelligent assumptions about the state of the DOM and the elements available to mutate. Custom namespaces conflict with this idea and change the schema of how different elements and attributes might work, so Inferno makes no attempt to support namespaces. Instead, SVG namespaces are automatically applied to elements and attributes based on their `tag name`.\n\n## Development\nIf you want to contribute code, fork this project and submit a PR from your fork. To run browser tests you need to build the repos. A complete rebuild of the repos can take >5 mins.\n\n```sh\n$ git clone git@github.com:infernojs/inferno.git\n$ cd inferno && npm i\n$ npm run test:node\n$ npm run build\n$ npm run test:browser\n```\n\nIf you only want to run the browser tests when coding, use the following to reduce turnaround by 50-80%:\n\n```sh\n$ npm run quick-test:browser # Compiles all packages and runs browser tests\n$ npm run quick-test:browser-inferno # Only compiles the inferno package and runs browser tests\n$ npm run quick-test:browser-debug # Compiles all packages and runs browser tests with \"debug\"\n```\n\n## Community\n\nThere is an InfernoJS Discord. You can join via [https://discord.gg/SUKuhgaBpF](https://discord.gg/SUKuhgaBpF).\n\n\n### Contributors\n\nThis project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].\n<a href=\"https://github.com/infernojs/inferno/graphs/contributors\"><img src=\"https://opencollective.com/inferno/contributors.svg?width=890\" /></a>\n\n\n### Backers\n\nThank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/inferno#backer)]\n\n<a href=\"https://opencollective.com/inferno#backers\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/backers.svg?width=890\"></a>\n\n\n### Sponsors\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/inferno#sponsor)]\n\n<a href=\"https://opencollective.com/inferno/sponsor/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/4/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/9/avatar.svg\"></a>\n\n"
  },
  {
    "path": "browser/jsfiddle-integration-babel7v3.js",
    "content": "document.addEventListener('DOMContentLoaded', function(event) {\n  Babel.registerPlugin(\"inferno\", window[\"babel-plugin-inferno\"]);\n  window.inferno = window.Inferno;\n\n  var tag = document.querySelector('script[type=\"application/javascript\"]');\n  if (!tag || tag.textContent.indexOf('window.onload=function(){') !== -1) {\n    alert('Bad JSFiddle configuration, please fork the original Inferno JSFiddle');\n  }\n  tag.setAttribute('type', 'text/babel');\n  tag.setAttribute('data-plugins', 'inferno,transform-modules-umd');\n  tag.setAttribute('data-presets', 'es2017');\n\n  tag.textContent = tag.textContent.replace(/^\\/\\/<!\\[CDATA\\[/, '');\n});\n"
  },
  {
    "path": "demo/inferno-router-demo/.babelrc",
    "content": "{\n  \"plugins\": [\n    \"inferno\"\n  ]\n}"
  },
  {
    "path": "demo/inferno-router-demo/.gitignore",
    "content": ".DS_Store\n.git/\n\n# VS Code specific\n.vscode\njsconfig.json\ntypings/*\ntypings.json\n\n# Dependency directory for NPM\nnode_modules\n\n# Built at startup\n.env\npwd.txt\nlerna-debug.log\n\ndist\ndistServer\ndistBrowser\npackage-lock.json\n.parcel-cache\n"
  },
  {
    "path": "demo/inferno-router-demo/.proxyrc",
    "content": "{\n  \"/api\": {\n    \"target\": \"http://127.0.0.1:3000/\"\n  }\n}"
  },
  {
    "path": "demo/inferno-router-demo/README.md",
    "content": "# Demo of Inferno-Router\n\nNOTE: Requires Nodejs >=18 (uses `fetch`)\n\n```sh\ncd demo/inferno-router-demo\nnpm i\nnpm run dev\n```\n\nGo to http://127.0.0.1:1234/\n"
  },
  {
    "path": "demo/inferno-router-demo/package.json",
    "content": "{\n  \"name\": \"inferno-router-demo\",\n  \"version\": \"8.0.5\",\n  \"description\": \"Influence CMS Demo\",\n  \"author\": \"Sebastian Ware <sebastian@urbantalk.se> (https://github.com/jhsware)\",\n  \"license\": \"SEE LICENSE IN LICENSE\",\n  \"source\": \"src/index.html\",\n  \"browserslist\": \"> 0.5%, last 2 versions, not dead\",\n  \"scripts\": {\n    \"dev:frontend\": \"cross-env FORCE_COLOR=1 parcel\",\n    \"dev:backend\": \"cross-env FORCE_COLOR=1 ts-node-dev --respawn src/server.ts\"\n  },\n  \"dependencies\": {\n    \"inferno\": \"file:../../packages/inferno\",\n    \"inferno-animation\": \"file:../../packages/inferno-animation\",\n    \"inferno-create-element\": \"file:../../packages/inferno-create-element\",\n    \"inferno-hydrate\": \"file:../../packages/inferno-hydrate\",\n    \"inferno-router\": \"file:../../packages/inferno-router\",\n    \"inferno-server\": \"file:../../packages/inferno-server\",\n    \"koa\": \"^2.15.3\",\n    \"koa-json-body\": \"^5.3.0\",\n    \"koa-logger\": \"^3.2.1\",\n    \"koa-mount\": \"^4.0.0\",\n    \"koa-router\": \"^13.0.1\",\n    \"koa-static\": \"^5.0.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/plugin-transform-modules-commonjs\": \"^7.25.9\",\n    \"@parcel/config-default\": \"^2.13.2\",\n    \"@parcel/packager-ts\": \"^2.13.2\",\n    \"@parcel/transformer-babel\": \"^2.13.2\",\n    \"@parcel/transformer-sass\": \"^2.13.2\",\n    \"@parcel/transformer-typescript-types\": \"^2.13.2\",\n    \"@types/node\": \"^22.10.0\",\n    \"babel-plugin-inferno\": \"^6.7.2\",\n    \"cross-env\": \"^7.0.3\",\n    \"jest-environment-jsdom\": \"^29.7.0\",\n    \"parcel\": \"^2.13.2\",\n    \"process\": \"^0.11.10\",\n    \"ts-node-dev\": \"^2.0.0\",\n    \"typescript\": \"^5.7.2\"\n  },\n  \"alias\": {\n    \"inferno\": \"inferno/dist/index.dev.mjs\",\n    \"inferno-animation\": \"inferno-animation/dist/index.dev.mjs\",\n    \"inferno-create-element\": \"inferno-create-element/dist/index.dev.mjs\",\n    \"inferno-hydrate\": \"inferno-hydrate/dist/index.dev.mjs\",\n    \"inferno-router\": \"inferno-router/dist/index.dev.mjs\",\n    \"inferno-server\": \"inferno-server/dist/index.dev.mjs\"\n  }\n}\n"
  },
  {
    "path": "demo/inferno-router-demo/src/App.tsx",
    "content": "import { Component } from 'inferno'\nimport { Route } from 'inferno-router'\n\n/**\n * Pages\n */\nimport StartPage from './pages/StartPage'\nimport AboutPage from './pages/AboutPage'\nimport ContentPage from './pages/ContentPage'\n\n/**\n * The Application\n */\nexport class App extends Component {\n  render(props) {\n    return props.children;\n  }\n};\n\nexport function appFactory () {\n\n  return (\n      <App>\n        {/* Public Pages */}\n        <Route exact path={`/`} component={ StartPage } />\n        <Route exact path={`/about`} component={ AboutPage } loader={AboutPage.fetchData} />\n        <Route exact path={`/page/:slug`} component={ ContentPage } loader={ContentPage.fetchData} />\n      </App>\n  )\n}\n"
  },
  {
    "path": "demo/inferno-router-demo/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\"/>\n    <title>Inferno Router Demo</title>\n    <script type=\"module\" src=\"index.tsx\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>"
  },
  {
    "path": "demo/inferno-router-demo/src/index.tsx",
    "content": "import { render } from 'inferno';\nimport { BrowserRouter } from 'inferno-router'\nimport { appFactory } from './App';\n\ndeclare global {\n  interface Window {\n    __initialData__: any\n  }\n}\n\nrender(<BrowserRouter initialData={window.__initialData__}>{appFactory()}</BrowserRouter>, document.getElementById('app'))\n"
  },
  {
    "path": "demo/inferno-router-demo/src/indexServer.tsx",
    "content": "import { hydrate } from 'inferno-hydrate';\nimport { BrowserRouter } from 'inferno-router'\nimport { appFactory } from './App';\n\ndeclare global {\n  interface Window {\n    __initialData__: any\n  }\n}\n\nhydrate(<BrowserRouter initialData={window.__initialData__}>{appFactory()}</BrowserRouter>, document.getElementById('app'))\n"
  },
  {
    "path": "demo/inferno-router-demo/src/pages/AboutPage.scss",
    "content": ""
  },
  {
    "path": "demo/inferno-router-demo/src/pages/AboutPage.tsx",
    "content": "import { Component } from 'inferno';\nimport PageTemplate from './PageTemplate';\nimport { useLoaderData } from 'inferno-router';\n\nimport './AboutPage.scss';\nimport { useLoaderError } from 'inferno-router';\n\nconst BACKEND_HOST = 'http://localhost:1234';\n\nexport default class AboutPage extends Component {\n  static async fetchData({ request }) {\n    const fetchOptions: RequestInit = {\n      headers: {\n        Accept: 'application/json',\n      },\n      signal: request?.signal,\n    };\n\n    return fetch(new URL('/api/about', BACKEND_HOST), fetchOptions);\n  }\n\n  render(props) {\n    const data = useLoaderData<{ title: string, body: string}>(props);\n    const err = useLoaderError<{ message: string }>(props);\n\n    return (\n      <PageTemplate>\n        <article>\n          <h1>{data?.title}</h1>\n          <p>{data?.body || err?.message}</p>\n        </article>\n      </PageTemplate>\n    );\n  }\n}\n"
  },
  {
    "path": "demo/inferno-router-demo/src/pages/ContentPage.scss",
    "content": ""
  },
  {
    "path": "demo/inferno-router-demo/src/pages/ContentPage.tsx",
    "content": "import { Component } from 'inferno';\nimport PageTemplate from './PageTemplate';\nimport { useLoaderData } from 'inferno-router';\n\nimport './AboutPage.scss';\nimport { useLoaderError } from 'inferno-router';\n\nconst BACKEND_HOST = 'http://localhost:1234';\n\nexport default class ContentPage extends Component {\n  static async fetchData({ params, request }) {\n    const pageSlug = params.id;\n\n    const fetchOptions: RequestInit = {\n      headers: {\n        Accept: 'application/json',\n      },\n      signal: request?.signal\n    };\n\n    return fetch(new URL(`/api/page/${params.slug}`, BACKEND_HOST), fetchOptions);\n  }\n\n  render(props) {\n    const data = useLoaderData<{ title: string, body: string}>(props);\n    const err = useLoaderError<{ message: string }>(props);\n\n    return (\n      <PageTemplate>\n        <article>\n          <h1>{data?.title}</h1>\n          <p>{data?.body || err?.message}</p>\n        </article>\n      </PageTemplate>\n    );\n  }\n}\n"
  },
  {
    "path": "demo/inferno-router-demo/src/pages/PageTemplate.scss",
    "content": ":root {\n  --rowGap: 2rem;\n}\n\n.page {\n  display: flex;\n  flex-flow: column nowrap;\n  min-height: 100vh;\n\n  h1, h2 {\n    margin-bottom: 1.5em;\n  }\n\n  header {\n    flex-grow: 0;\n    & > nav > ul {\n      display: flex;\n      flex-flow: row wrap;\n      gap: var(--rowGap);\n      align-items: center;\n      justify-content: center;\n      padding: 0;\n\n      & > li {\n        list-style: none;\n      }\n    }\n  }\n  main {\n    flex-grow: 1;\n    display: flex;\n    flex-flow: column;\n    align-items: center;\n    justify-content: flex-start;\n    text-align: center;\n\n    & > * {\n      max-width: 50rem\n    }\n\n    & > .body {\n      width: 100%;\n    }\n  }\n  footer {\n    flex-grow: 0\n  }\n}\n"
  },
  {
    "path": "demo/inferno-router-demo/src/pages/PageTemplate.tsx",
    "content": "import { Link } from 'inferno-router'\n\nimport './PageTemplate.scss'\n\nexport default function PageTemplate({ id = undefined, children }) {\n  return (\n    <div id={id} className=\"page\">\n      <header>\n        <nav>\n          <ul>\n            <li><Link to=\"/\">Start</Link></li>\n            <li><Link to=\"/about\">About</Link></li>\n            <li><Link to=\"/page/one\">Page One</Link></li>\n            <li><Link to=\"/page/two\">Page Two</Link></li>\n          </ul>\n        </nav>\n      </header>\n      <main>{children}</main>\n      <footer>\n        <p>Page Footer</p>\n      </footer>\n    </div>\n  )\n\n}\n"
  },
  {
    "path": "demo/inferno-router-demo/src/pages/StartPage.scss",
    "content": ""
  },
  {
    "path": "demo/inferno-router-demo/src/pages/StartPage.tsx",
    "content": "import { Component } from 'inferno'\nimport PageTemplate from './PageTemplate'\nimport './StartPage.scss'\n\ninterface IProps {\n  fetchData: any;\n}\n\nexport default class StartPage extends Component<IProps> {\n  static async fetchData({ match }) {\n    const pageSlug = match.params.id\n    return [];\n  }\n\n  render() {\n    return (\n      <PageTemplate>\n        <article>\n          <h1>Start Page</h1>\n          <p>Some content</p>\n        </article>\n      </PageTemplate>\n    )\n  }\n}\n"
  },
  {
    "path": "demo/inferno-router-demo/src/server.ts",
    "content": "import * as koa from 'koa'; // koa@2\nimport * as logger from 'koa-logger';\nimport * as koaRouter from 'koa-router'; // koa-router@next\nimport * as koaStatic from 'koa-static';\nimport * as koaMount from 'koa-mount';\nimport { renderToString } from 'inferno-server';\nimport { StaticRouter, resolveLoaders, traverseLoaders } from 'inferno-router'\nimport {Parcel} from '@parcel/core';\nimport { createElement } from 'inferno-create-element';\n\nconst PORT = process.env.PORT || 3000;\nconst BASE_URI = `http://localhost:${PORT}`;\n\n// Parcel watch subscription and bundle output\n// NOTE: Currently deactivated watcher (the following line and `bundler.watch` further down)\n// let subscription;\nlet bundles;\n\nlet bundler = new Parcel({\n  // NOTE: Specifying target: { source: './src/App.tsx' } didn't work for me\n  entries: ['./src/App.tsx', './src/indexServer.tsx'],\n  defaultConfig: '@parcel/config-default',\n  targets: {\n    default: {\n      context: 'node',\n      engines: {\n        node: \">=18\"\n      },\n      distDir: \"./distServer\",\n      publicUrl: \"/\", // Should be picked up from environment\n    },\n    browser: {\n      context: 'browser',\n      engines: {\n        browsers: '> 0.5%, last 2 versions, not dead'\n      },\n      distDir: \"./distBrowser\",\n      publicUrl: \"/\", // Should be picked up from environment\n    }\n  },\n  mode: 'development'\n});\n\n\nconst app = new koa()\nconst api = new koaRouter()\nconst frontend = new koaRouter()\n\n/**\n * Logging\n */\napp.use(logger((str, args) => {\n  console.log(str)\n}))\n\n/**\n * Endpoint for healthcheck\n */\napi.get('/api/ping', (ctx) => {\n  ctx.body = 'ok';\n});\napi.get('/api/about', async (ctx) => {\n\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      ctx.body = {\n        title: \"Inferno-Router\",\n        body: \"Routing with async data loader support.\"\n      };\n      resolve(null);\n    }, 500)\n  })\n});\n\napi.get('/api/page/:slug', async (ctx) => {\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      ctx.body = {\n        title: ctx.params.slug.toUpperCase(),\n        body: \"This is a page.\"\n      };\n      resolve(null);\n    }, 1300)\n  })\n});\n\nfunction renderPage(html, initialData) {\n  return `<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\"/>\n    <title>Inferno Router Demo</title>\n    <link rel=\"stylesheet\" href=\"/dist/App.css\"/>\n    <script type=\"module\" src=\"/dist/indexServer.js\"></script>\n    <script>\n    window.__initialData__ = ${JSON.stringify(initialData)};\n    </script>\n  </head>\n  <body>\n    <div id=\"app\">${html}</div>\n  </body>\n</html>  \n`\n}\n\nfrontend.get('(/page)?/:slug?', async (ctx) => {\n  const location = ctx.path;\n\n  const pathToAppJs  = bundles.find(b => b.name === 'App.js' && b.env.context === 'node').filePath;\n  const { appFactory } = require(pathToAppJs)\n  const app = appFactory();\n\n  const loaderEntries = traverseLoaders(location, app, BASE_URI);\n  const initialData = await resolveLoaders(loaderEntries);\n\n  const htmlApp = renderToString(createElement(StaticRouter, {\n    context: {},\n    location,\n    initialData,\n  }, app))\n\n  ctx.body = renderPage(htmlApp, initialData);\n})\n\n\n/**\n * Mount all the routes for Koa to handle\n */\napp.use(api.routes());\napp.use(api.allowedMethods());\napp.use(frontend.routes());\napp.use(frontend.allowedMethods());\napp.use(koaMount('/dist', koaStatic('distBrowser')));\n\n// bundler.watch((err, event) => {\n//   if (err) {\n//     // fatal error\n//     throw err;\n//   }\n\n//   if (event.type === 'buildSuccess') {\n//     bundles = event.bundleGraph.getBundles();\n//     console.log(`✨ Built ${bundles.length} bundles in ${event.buildTime}ms!`);\n//   } else if (event.type === 'buildFailure') {\n//     console.log(event.diagnostics);\n//   }\n// }).then((sub => subscription = sub));\n\napp.listen(PORT, async () => {\n  \n  // Trigger first transpile\n  // https://parceljs.org/features/parcel-api/\n  try {\n    let {bundleGraph, buildTime} = await bundler.run();\n    bundles = bundleGraph.getBundles();\n    console.log(`✨ Built ${bundles.length} bundles in ${buildTime}ms!`);\n  } catch (err) {\n    console.log(err.diagnostics);\n  }\n\n  console.log('Server listening on: ' + PORT)\n})\n"
  },
  {
    "path": "demo/inferno-router-demo/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"module\": \"commonjs\",\n    \"target\": \"es2020\",\n    \"moduleResolution\": \"Node\",\n    \"jsx\": \"preserve\",\n    \"lib\": [\n      \"dom\",\n      \"es2022\"\n    ],\n    \"types\": [\n      \"inferno\",\n      \"node\"\n    ],\n  }\n}\n"
  },
  {
    "path": "docs/1kcomponents/app.js",
    "content": "import { Component, render } from 'inferno';\n// import { startFPSMonitor, startMemMonitor } from 'perf-monitor';\nimport { interpolateViridis } from 'd3-scale-chromatic';\n\n// startFPSMonitor();\n// startMemMonitor();\n\nfunction map(arr, to) {\n  let out = [];\n  for (let i = 0; i < arr.length; i++) {\n    out.push(to(arr[i]));\n  }\n  return out;\n}\n\nclass Demo extends Component {\n  constructor(props, context) {\n    super(props, context);\n\n    this.state = {\n      numPoints: 0\n    };\n\n    this.updateCount = this.updateCount.bind(this);\n  }\n\n  updateCount(e) {\n    this.setState({\n      numPoints: e.target.value\n    });\n  }\n\n  componentDidMount() {\n    this.setState({\n      numPoints: 1000\n    });\n  }\n\n  render(props, state) {\n    return (\n      <div className=\"app-wrapper\">\n        <VizDemo count={state.numPoints} />\n        <div className=\"controls\">\n          # Points\n          <input type=\"range\" min={10} max={10000} value={state.numPoints} onInput={this.updateCount} />\n          {state.numPoints}\n        </div>\n        <div className=\"about\">\n          InfernoJS 1k Components Demo based on the Glimmer demo by{' '}\n          <a href=\"http://mlange.io\" target=\"_blank\">\n            Michael Lange\n          </a>\n          .\n        </div>\n      </div>\n    );\n  }\n}\n\nconst Layout = {\n  PHYLLOTAXIS: 0,\n  GRID: 1,\n  WAVE: 2,\n  SPIRAL: 3\n};\n\nconst LAYOUT_ORDER = [Layout.PHYLLOTAXIS, Layout.SPIRAL, Layout.PHYLLOTAXIS, Layout.GRID, Layout.WAVE];\n\nclass VizDemo extends Component {\n  constructor(props, context) {\n    super(props, context);\n\n    this.layout = 0;\n    this.phyllotaxis = genPhyllotaxis(100);\n    this.grid = genGrid(100);\n    this.wave = genWave(100);\n    this.spiral = genSpiral(100);\n    this.points = [];\n    this.step = 0;\n    this.numSteps = 60 * 2;\n  }\n\n  next() {\n    this.step = (this.step + 1) % this.numSteps;\n\n    if (this.step === 0) {\n      this.layout = (this.layout + 1) % LAYOUT_ORDER.length;\n    }\n\n    // Clamp the linear interpolation at 80% for a pause at each finished layout state\n    const pct = Math.min(1, this.step / (this.numSteps * 0.8));\n\n    const currentLayout = LAYOUT_ORDER[this.layout];\n    const nextLayout = LAYOUT_ORDER[(this.layout + 1) % LAYOUT_ORDER.length];\n\n    // Keep these redundant computations out of the loop\n    const pxProp = xForLayout(currentLayout);\n    const nxProp = xForLayout(nextLayout);\n    const pyProp = yForLayout(currentLayout);\n    const nyProp = yForLayout(nextLayout);\n\n    this.points = this.points.map((point) => {\n      const newPoint = { ...point };\n      newPoint.x = lerp(newPoint, pct, pxProp, nxProp);\n      newPoint.y = lerp(newPoint, pct, pyProp, nyProp);\n      return newPoint;\n    });\n\n    this.setState();\n    requestAnimationFrame(() => {\n      this.next();\n    });\n  }\n\n  setAnchors(arr) {\n    arr.map((p, index) => {\n      const [gx, gy] = project(this.grid(index));\n      const [wx, wy] = project(this.wave(index));\n      const [sx, sy] = project(this.spiral(index));\n      const [px, py] = project(this.phyllotaxis(index));\n\n      Object.assign(p, { gx, gy, wx, wy, sx, sy, px, py });\n    });\n\n    this.points = arr;\n  }\n\n  makePoints(count) {\n    const newPoints = [];\n    for (var i = 0; i < count; i++) {\n      newPoints.push({\n        x: 0,\n        y: 0,\n        color: interpolateViridis(i / count)\n      });\n    }\n    this.setAnchors(newPoints);\n  }\n\n  componentWillReceiveProps(props) {\n    if (props.count !== this.props.count) {\n      this.phyllotaxis = genPhyllotaxis(props.count);\n      this.grid = genGrid(props.count);\n      this.wave = genWave(props.count);\n      this.spiral = genSpiral(props.count);\n\n      this.makePoints(props.count);\n    }\n  }\n\n  componentDidMount() {\n    this.next();\n  }\n\n  renderPoint(point) {\n    return <Point x={point.x} y={point.y} color={point.color} />;\n  }\n\n  render() {\n    return (\n      <svg className=\"demo\">\n        <g $HasNonKeyedChildren>{map(this.points, this.renderPoint)}</g>\n      </svg>\n    );\n  }\n}\n\nfunction Point({ x, y, color }) {\n  return <rect className=\"point\" transform={`translate(${Math.floor(x)}, ${Math.floor(y)})`} fill={color} />;\n}\nconst theta = Math.PI * (3 - Math.sqrt(5));\n\nfunction xForLayout(layout) {\n  switch (layout) {\n    case Layout.PHYLLOTAXIS:\n      return 'px';\n    case Layout.GRID:\n      return 'gx';\n    case Layout.WAVE:\n      return 'wx';\n    case Layout.SPIRAL:\n      return 'sx';\n  }\n}\n\nfunction yForLayout(layout) {\n  switch (layout) {\n    case Layout.PHYLLOTAXIS:\n      return 'py';\n    case Layout.GRID:\n      return 'gy';\n    case Layout.WAVE:\n      return 'wy';\n    case Layout.SPIRAL:\n      return 'sy';\n  }\n}\n\nfunction lerp(obj, percent, startProp, endProp) {\n  let px = obj[startProp];\n  return px + (obj[endProp] - px) * percent;\n}\n\nfunction genPhyllotaxis(n) {\n  return (i) => {\n    let r = Math.sqrt(i / n);\n    let th = i * theta;\n    return [r * Math.cos(th), r * Math.sin(th)];\n  };\n}\n\nfunction genGrid(n) {\n  let rowLength = Math.round(Math.sqrt(n));\n  return (i) => [-0.8 + (1.6 / rowLength) * (i % rowLength), -0.8 + (1.6 / rowLength) * Math.floor(i / rowLength)];\n}\n\nfunction genWave(n) {\n  let xScale = 2 / (n - 1);\n  return (i) => {\n    let x = -1 + i * xScale;\n    return [x, Math.sin(x * Math.PI * 3) * 0.3];\n  };\n}\n\nfunction genSpiral(n) {\n  return (i) => {\n    let t = Math.sqrt(i / (n - 1)),\n      phi = t * Math.PI * 10;\n    return [t * Math.cos(phi), t * Math.sin(phi)];\n  };\n}\n\nfunction scale(magnitude, vector) {\n  return vector.map((p) => p * magnitude);\n}\n\nfunction translate(translation, vector) {\n  return vector.map((p, i) => p + translation[i]);\n}\n\nfunction project(vector) {\n  const wh = window.innerHeight / 2;\n  const ww = window.innerWidth / 2;\n  return translate([ww, wh], scale(Math.min(wh, ww), vector));\n}\n\nrender(<Demo />, document.getElementById('app'));\n"
  },
  {
    "path": "docs/1kcomponents/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <meta charset=\"utf-8\"/>\n    <link rel=\"stylesheet\" href=\"style.css\">\n</head>\n<body>\n<div id=\"app\"></div>\n<script src=\"dist/bundle.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/1kcomponents/style.css",
    "content": "html,\nbody {\n    padding: 0;\n    margin: 0;\n    font-family: sans-serif;\n    width: 100%;\n    height: 100%;\n    background: #111;\n    color: #777;\n}\n\na {\n    color: #777;\n}\n\n.demo {\n    overflow-x: hidden;\n    position: relative;\n}\n.point {\n    width: 4px;\n    height: 4px;\n    position: absolute;\n    shape-rendering: optimizeSpeed;\n}\n.controls {\n    position: fixed;\n    top: 0;\n    width: 100%;\n    padding: 15px;\n    background: #e41f1c;\n    border-bottom: 1px solid darkred;\n    display: -webkit-box;\n    display: -ms-flexbox;\n    display: flex;\n    -webkit-box-pack: center;\n    -ms-flex-pack: center;\n    justify-content: center;\n    color: white;\n    white-space: nowrap;\n}\n.controls > input {\n    margin: 0 10px;\n    width: 50%;\n}\n.controls label {\n    margin-left: 30px;\n}\n#stats {\n    position: fixed;\n    top: 0;\n    right: 0;\n}\n.about {\n    position: fixed;\n    bottom: 0;\n    width: 100%;\n    padding: 10px;\n}\n#app,\n.app-wrapper,\n.demo {\n    width: 100%;\n    height: 100%;\n    overflow: hidden;\n}\n"
  },
  {
    "path": "docs/animations/app.css",
    "content": ":root {\n  --infernoAnimationEnter: border-width .25s ease-out, padding .25s ease-out, height .25s ease-out, opacity .6s ease-in;\n  --infernoAnimationLeave: border-width .25s ease-out, padding 1s ease-out, height 1s ease-out, opacity 1.2s ease-in;\n  --fadeAnimationEnter: opacity 0.1s ease-in;\n  --fadeAnimationLeave: opacity 2s ease-out;\n\n  --movePlaceholderAnimation: height 1s, border-width 1s, padding 1s;\n  --moveAnimation: transform 1s;\n}\n\n/******************************/\n/* Animate height and opacity */\n/******************************/\n.HeightAndFade-leave {\n    /* Leave animation start state */\n    opacity: 1;\n}\n\n.HeightAndFade-leave-active {\n    /* Leave animation transitions */\n    overflow: hidden;\n    transition: var(--infernoAnimationLeave);\n}\n\n.HeightAndFade-leave-end {\n    /* Leave animation end state */\n    opacity: 0;\n    height: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    border-width: 0;\n}\n\n.HeightAndFade-enter {\n    /* Enter animation start state */\n    opacity: 0;\n    height: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    border-width: 0;\n}\n\n.HeightAndFade-enter-active {\n    /* Enter animation transitions */\n    transition: var(--infernoAnimationEnter);\n}\n\n.HeightAndFade-enter-end {\n    /* Enter animation end state */\n    opacity: 1;\n}\n\n/*************************/\n/* Simple fade animation */\n/*************************/\n.fade-enter,\n.fade-leave-end {\n  opacity: 0;\n}\n\n.fade-enter-end,\n.fade-leave {\n  opacity: 1;\n}\n\n.fade-leave-active {\n  /* Leave animation transitions */\n  transition: var(--fadeAnimationLeave);\n}\n\n.fade-enter-active {\n  /* Enter animation transitions */\n  transition: var(--fadeAnimationEnter);\n}\n\n/*****************/\n/* Animate moves */\n/*****************/\n.MoveAnim-move-active {\n  --moveAnimation: ;\n  /* Move animation transitions */\n  transition: transform 1.5s; /*var(--moveAnimation);*/\n  z-index: 1;\n  opacity: 0.6;\n}\n\n/***************************/\n/* General styling of page */\n/***************************/\n\narticle,\nul {\n  box-sizing: border-box;\n  margin: 0;\n  padding: 0;\n  list-style: none;\n  margin-bottom: 0.5rem;\n}\n\nsection,\nli {\n  box-sizing: border-box;\n  padding: 0.5rem 1rem;\n  background: #4A90E2;\n  color: white;\n  text-align: center;\n  max-width: 10rem;\n  border-top: 1px solid #fff;\n}\n\nsection:hover,\nli:hover {\n  background: #3775bb;\n}\n\nspan.divider,\nli.divider {\n  display: block;\n  height: 5px;\n  background: #ccc;\n  border-width: 0;\n}\n\nbutton {\n  padding: 0.5rem 1rem;\n  margin-top: 0.5rem;\n  display: block;\n  background: #35a748;\n  color: white;\n  border-style: none;\n  border-radius: 4px;\n  width: 10rem;\n} button:hover {\n  background: #3775bb;\n}\n\nbody {\n  font-family: helvetica;\n  box-sizing: border-box;\n  margin: 0;\n  padding: 1rem;\n  display: flex;\n  gap: 2rem;\n  justify-content: center;\n  align-items: flex-end;\n  height: 100vh;\n  overflow-y: scroll;\n}\n\n.App {\n  box-sizing: border-box;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: flex-end;\n  padding: 1rem;\n}\n\nh1 {\n  transform: rotate(-90deg);\n  font-size: 2rem;\n  font-weight: 800;\n  color: #ddd;\n  text-align: center;\n  margin: 0.5rem;\n  white-space: nowrap;\n  width: 2rem;\n  transform-origin: 50% 50%;\n}\n\nh1 small {\n  font-size: 0.5em;\n}\nh1 small a {\n  color: #4A90E2;\n  text-decoration: none;\n}\nh1 small a:hover {\n  color: #3775bb;\n}\n\nh2 {\n  font-size: 1rem;\n  font-weight: 100;\n  color: #4A90E2;\n  text-align: center;\n}\n\np {\n  width: 10rem;\n  font-size: 0.65rem;\n  font-weight: 100;\n  color: #888;\n  text-align: center;\n  margin-top: -0.5em;\n}\n\n/**\n * Debug markers\n * To render debug markers, set _DBG_MVE_ = true in animations.ts\n **/\n\n.debugMarker {\n  display: block;\n  position: absolute;\n  transform: translate(calc(-100% - 7px), -50%);\n  padding-right: 15px;\n  z-index: 999;\n  font-size: 10px;\n}\n\n.debugMarker-src:after {\n  position: absolute;\n  content: '';\n  right: -15px;\n  top: 50%;\n  transform: translateY(-50%);\n  border: 10px solid transparent;\n  border-left-color: red;\n  opacity: 0.3;\n}\n\n.debugMarker-src {\n  transform: translate(calc(-200% - 7px), -50%);\n}\n\n.debugMarker-trg:after {\n  position: absolute;\n  content: '';\n  right: -15px;\n  top: 50%;\n  transform: translateY(-50%);\n  border: 10px solid transparent;\n  border-left-color: green;\n  opacity: 0.3;\n}\n"
  },
  {
    "path": "docs/animations/app.js",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport { AnimatedComponent, AnimatedMoveComponent, componentDidAppear, componentWillDisappear, componentWillMove, utils } from 'inferno-animation';\n\nvar { addClassName, removeClassName, forceReflow, registerTransitionListener } = utils;\n\nlet renderCounter = 0;\n\nconst anim = {\n  onComponentDidAppear: componentDidAppear,\n  onComponentWillDisappear: componentWillDisappear\n};\n\nconst animMove = {\n  onComponentWillMove: componentWillMove\n};\n\nclass ListItem extends AnimatedComponent {\n  render() {\n    renderCounter++;\n    return createElement('li', { onClick: (e) => this.props.onClick(e, this.props.index) }, this.props.children);\n  }\n}\n\nclass SectionItem extends AnimatedComponent {\n  render() {\n    renderCounter++;\n    return createElement('section', { onClick: (e) => this.props.onClick(e, this.props.index) }, this.props.children);\n  }\n}\n\nconst FuncListItem = ({ children, ...props }) => {\n  renderCounter++;\n  return createElement('li', { onClick: (e) => props.onClick(e, props.index) }, children);\n};\n\nconst FuncSectionItem = ({ children, ...props }) => {\n  renderCounter++;\n  return createElement('section', { onClick: (e) => props.onClick(e, props.index) }, children);\n};\n\nclass ListItemMoveAnim extends AnimatedMoveComponent {\n  render() {\n    renderCounter++;\n    return createElement('li', { onClick: (e) => this.props.onClick(e, this.props.index) }, this.props.children);\n  }\n}\n\nconst FuncListItemMoveAnim = ({ children, ...props }) => {\n  renderCounter++;\n  return createElement('li', { onClick: (e) => props.onClick(e, props.index) }, children);\n};\n\nclass List extends Component {\n  constructor() {\n    super();\n\n    this.state = {\n      items: []\n    };\n    this.items = [];\n  }\n\n  doRemove = (e, index) => {\n    e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    newItems.splice(index, 1);\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doAdd = (e) => {\n    e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    var nextKey = newItems.length === 0 ? 0 : newItems[newItems.length - 1].key + 1;\n    newItems.push({ key: nextKey });\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doRemove20 = (e) => {\n    e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    newItems.splice(newItems.length >= 20 ? newItems.length - 20 : 0, newItems.length >= 20 ? 20 : newItems.length);\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doAdd20 = (e) => {\n    e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    var nextKey = newItems.length === 0 ? 0 : newItems[newItems.length - 1].key + 1;\n    for (var i = 0; i < 20; i++) {\n      newItems.push({ key: nextKey + i });\n    }\n    this.setState({\n      items: newItems\n    });\n  };\n\n  componentDidMount() {\n    let i = 0;\n\n    while (this.items.length < 20) {\n      this.items[this.items.length] = { key: i++ };\n    }\n    this.setState({ items: this.items });\n  }\n\n  renderItem = (item, i) => {\n    if (this.props.useFunctionalComponent) {\n      return createElement(FuncListItem, { key: item.key, index: i, animation: this.props.animation, ...anim, onClick: this.doRemove }, `${item.key + 1}bar`);\n    } else {\n      return createElement(ListItem, { key: item.key, index: i, animation: this.props.animation, onClick: this.doRemove }, `${item.key + 1}bar`);\n    }\n  };\n\n  render() {\n    return createElement('div', null, [\n      createElement('ul', null, this.state.items.map(this.renderItem)),\n      createElement('h2', null, this.props.animation),\n      createElement('p', null, this.props.description),\n      createElement('button', { onClick: this.doAdd }, 'Add'),\n      createElement('button', { onClick: this.doAdd20 }, 'Add 20'),\n      createElement('button', { onClick: this.doRemove20 }, 'Remove 20')\n    ]);\n  }\n}\n\nclass MixedList extends Component {\n  constructor() {\n    super();\n\n    let i = 0;\n    let items = [];\n    while (items.length < 40) {\n      items[items.length] = { key: i++, isListItem: true };\n      items[items.length] = { key: i++ };\n    }\n\n    this.state = {\n      items\n    };\n  }\n\n  componentDidAppear = (dom) => {\n    const animCls = {\n      start: 'fade-enter',\n      active: 'fade-enter-active',\n      end: 'fade-enter-end'\n    };\n    // 1. Set animation start state\n    addClassName(dom, animCls.start);\n    forceReflow();\n\n    // 2. Activate transition\n    addClassName(dom, animCls.active);\n\n    // 3. Set an animation listener, code at end\n    // Needs to be done after activating so timeout is calculated correctly\n    registerTransitionListener([dom], function () {\n      // *** Cleanup ***\n      // 5. Remove the element\n      removeClassName(dom, animCls.active);\n      removeClassName(dom, animCls.end);\n    });\n\n    // 4. Activate target state\n    requestAnimationFrame(() => {\n      removeClassName(dom, animCls.start);\n      addClassName(dom, animCls.end);\n    });\n  };\n\n  componentWillDisappear = (dom, callback) => {\n    const animCls = {\n      start: 'fade-leave',\n      active: 'fade-leave-active',\n      end: 'fade-leave-end'\n    };\n\n    // 1. Set animation start state\n    addClassName(dom, animCls.start);\n\n    // 2. Activate transitions\n    addClassName(dom, animCls.active);\n\n    // 3. Set an animation listener, code at end\n    // Needs to be done after activating so timeout is calculated correctly\n    registerTransitionListener([dom], function () {\n      // *** Cleanup ***\n\n      // Simulate some work is being done\n      // setTimeout(function () {\n      //   callback();\n      // }, 1000);\n      callback();\n    });\n\n    // 4. Activate target state\n    requestAnimationFrame(() => {\n      addClassName(dom, animCls.end);\n      removeClassName(dom, animCls.start);\n    });\n  };\n\n  doRemove = (e, index) => {\n    e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    newItems.splice(index, 1);\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doRemoveSpecial = (e) => {\n    e.preventDefault();\n    // Remove random ListItem and trigger animation\n    var onlyListItems = this.state.items.filter((item) => item.isListItem);\n    var toDeleteIndex = parseInt(Math.round(Math.random() * (onlyListItems.length - 1)));\n    var toDeleteKey = onlyListItems[toDeleteIndex].key;\n    var newItems = this.state.items.filter((item) => item.key !== toDeleteKey);\n    this.setState({\n      items: newItems\n    });\n\n    // Remove random divider during animation\n    // NOTE! If the divider is the last element, it will cause everything to be removed,\n    // thus cutting the running animation short. This is expected behaviour because we don't\n    // check if the parent has an animating child. Opportunity for improvement.\n    setTimeout(() => {\n      var onlyDividers = this.state.items.filter((item) => !item.isListItem);\n      var toDeleteIndex = parseInt(Math.round(Math.random() * (onlyDividers.length - 1)));\n      var counter = 0;\n      var newItems = this.state.items.filter((item) => item.isListItem || counter++ !== toDeleteIndex);\n      this.setState({\n        items: newItems\n      });\n    }, 100);\n  };\n\n  doAdd = (e) => {\n    e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    var nextKey = newItems.reduce((prev, curr) => (curr.key > prev ? curr.key : prev), 0) + 1;\n    newItems.push({ key: nextKey, isListItem: true });\n    newItems.push({ key: nextKey + 1 });\n    this.setState({\n      items: newItems\n    });\n  };\n\n  renderItem = (item, i) => {\n    if (this.props.useFunctionalComponent) {\n      return createElement(\n        FuncSectionItem,\n        { key: item.key, index: i, animation: this.props.animation, ...anim, onClick: this.doRemove },\n        `${item.key + 1}bar`\n      );\n    } else {\n      return createElement(SectionItem, { key: item.key, index: i, animation: this.props.animation, onClick: this.doRemove }, `${item.key + 1}bar`);\n    }\n  };\n\n  render() {\n    // Mixing <section> and <span> instead of using <li> for all to trigger special code path in Inferno\n    return createElement('div', null, [\n      createElement(\n        'article',\n        null,\n        this.state.items.map((item, i) => (item.isListItem ? this.renderItem(item, i) : createElement('span', { className: 'divider' })))\n      ),\n      createElement('h2', null, 'Mixed list'),\n      createElement('p', null, this.props.description),\n      createElement('button', { onClick: this.doAdd }, 'Add'),\n      createElement('button', { onClick: this.doRemoveSpecial }, 'Remove')\n    ]);\n  }\n}\n\nclass ShuffleList extends Component {\n  constructor() {\n    super();\n    // set initial time:\n    this.state = {\n      items: []\n    };\n    this.items = [];\n  }\n\n  doRemove = (e, index) => {\n    e && e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    newItems.splice(index, 1);\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doAdd = (e) => {\n    e && e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    var nextKey = newItems.reduce((prev, curr) => (curr.key > prev ? curr.key : prev), 0) + 1;\n    newItems.push({ key: nextKey, val: nextKey });\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doMix = (e) => {\n    e && e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    shuffle(newItems);\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doReassignKeys = (e) => {\n    e && e.preventDefault();\n    var tmpItems = this.state.items.concat([]);\n    shuffle(tmpItems);\n    var newItems = this.state.items.map((item, index) => {\n      return Object.assign({}, item, { key: tmpItems[index].key });\n    });\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doRemoveMix = (e) => {\n    e && e.preventDefault();\n    if (this.state.items.length === 0) {\n      return;\n    }\n    // Remove random ListItem and trigger animation\n    var toDeleteIndex = parseInt(Math.round(Math.random() * (this.state.items.length - 1)));\n    var toDeleteKey = this.state.items[toDeleteIndex].key;\n    var newItems = this.state.items.filter((item) => item.key !== toDeleteKey);\n    this.setState({\n      items: newItems,\n      deleted: toDeleteKey + 1\n    });\n\n    setTimeout(() => this.doMix(e), 100);\n  };\n\n  removeAndShuffle = (e) => {\n    e && e.preventDefault();\n    for (let i = 0; i < 20; i++) {\n      setTimeout(() => {\n        var toDeleteIndex = parseInt(Math.round(Math.random() * (this.state.items.length - 1)));\n        this.doRemove(undefined, toDeleteIndex);\n        this.doReassignKeys();\n        this.doMix();\n      });\n    }\n  };\n\n  doAdd20 = (e) => {\n    e && e.preventDefault();\n    // Add data\n    for (let i = 0; i < 20; i++) {\n      this.doAdd();\n    }\n    // Shuffle them\n    for (let i = 0; i < 5; i++) {\n      this.doReassignKeys();\n      this.doMix();\n    }\n  };\n\n  doAdd20SeqMix = (e) => {\n    e && e.preventDefault();\n    // Add data\n    for (let i = 0; i < 20; i++) {\n      this.doAdd();\n    }\n    // Shuffle them\n    for (let i = 0; i < 5; i++) {\n      setTimeout(\n        () => {\n          // this.doReassignKeys(e);\n          this.doMix();\n        },\n        500 + 100 * i\n      );\n    }\n  };\n\n  componentDidMount() {\n    let i = 0;\n\n    while (this.items.length < 20) {\n      this.items[this.items.length] = { key: i, val: i };\n      i++;\n    }\n    this.setState({ items: this.items });\n  }\n\n  renderItem = (item, i) => {\n    if (this.props.useFunctionalComponent) {\n      return createElement(\n        FuncListItem,\n        { key: item.key, index: i, animation: this.props.animation, ...anim, onClick: this.doRemove },\n        `${item.val}bar (${item.key})`\n      );\n    } else {\n      return createElement(ListItem, { key: item.key, index: i, animation: this.props.animation, onClick: this.doRemove }, `${item.val}bar (${item.key})`);\n    }\n  };\n\n  render() {\n    return createElement('div', null, [\n      createElement('ul', null, this.state.items.map(this.renderItem)),\n      createElement('h2', null, 'Shuffle'),\n      createElement('p', null, this.props.description),\n      createElement('button', { onClick: this.doAdd }, 'Add'),\n      createElement('button', { onClick: this.doMix }, 'Shuffle'),\n      createElement('button', { onClick: this.doReassignKeys }, 'Shuffle keys'),\n      createElement('button', { onClick: this.doRemoveMix }, 'Remove' + (this.state.deleted ? ` (${this.state.deleted})` : '')),\n      createElement('button', { onClick: this.doAdd20 }, 'Add and shuffle 20'),\n      createElement('button', { onClick: this.doAdd20SeqMix }, 'Add 20 do 5 shuffle'),\n      createElement('button', { onClick: this.removeAndShuffle }, 'Remove and shuffle 20')\n    ]);\n  }\n}\n\n// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array\nvar shuffle = (array) => {\n  var currentIndex = array.length,\n    temporaryValue,\n    randomIndex;\n\n  // While there remain elements to shuffle...\n  while (0 !== currentIndex) {\n    // Pick a remaining element...\n    randomIndex = Math.floor(Math.random() * currentIndex);\n    currentIndex -= 1;\n\n    // And swap it with the current element.\n    temporaryValue = array[currentIndex];\n    array[currentIndex] = array[randomIndex];\n    array[randomIndex] = temporaryValue;\n  }\n\n  return array;\n};\n\nclass RerenderList extends Component {\n  constructor() {\n    super();\n    // set initial time:\n    this.state = {\n      items: []\n    };\n    this.items = [];\n  }\n\n  doRemove = (e, index) => {\n    e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    newItems.splice(index, 1);\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doAdd = (e) => {\n    e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    var nextKey = newItems.reduce((prev, curr) => (curr.key > prev ? curr.key : prev), 0) + 1;\n    newItems.push({ key: nextKey, val: nextKey });\n    this.setState({\n      items: newItems\n    });\n  };\n\n  componentDidMount() {\n    this.componentWillReceiveProps(this.props);\n  }\n\n  componentWillReceiveProps(nextProps) {\n    let i = 0;\n\n    while (this.items.length < nextProps.items) {\n      this.items[this.items.length] = { key: i, val: i };\n      i++;\n    }\n    this.setState({ items: this.items });\n  }\n\n  renderItem = (item, i) => {\n    if (this.props.useFunctionalComponent) {\n      return createElement(\n        FuncListItem,\n        { key: item.key, index: i, animation: this.props.animation, ...anim, onClick: this.doRemove },\n        `${item.val}bar (${item.key})`\n      );\n    } else {\n      return createElement(ListItem, { key: item.key, index: i, animation: this.props.animation, onClick: this.doRemove }, `${item.val}bar (${item.key})`);\n    }\n  };\n\n  render() {\n    return createElement('div', null, [\n      createElement('ul', null, this.state.items.map(this.renderItem)),\n      createElement('h2', null, 'patchKeyedChildren'),\n      createElement('p', null, this.props.description),\n      createElement('button', { onClick: this.doAdd }, 'Add')\n    ]);\n  }\n}\n\nclass ShuffleListWithAnimation extends Component {\n  constructor() {\n    super();\n    // set initial time:\n    this.state = {\n      items: []\n    };\n    this.items = [];\n  }\n\n  doMove = (e, index) => {\n    e && e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    var [tmp] = newItems.splice(index, 1);\n    newItems.splice(Math.round(Math.random() * newItems.length), 0, tmp);\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doAdd = (e) => {\n    e && e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    var nextKey = newItems.reduce((prev, curr) => (curr.key > prev ? curr.key : prev), 0) + 1;\n    newItems.push({ key: nextKey, val: nextKey });\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doMix = (e) => {\n    e && e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    shuffle(newItems);\n\n    // So this is the shuffled order\n    console.log('Expected order: ' + newItems.map((el) => '(' + el.val + ')').join(','));\n\n    this.setState({\n      items: newItems\n    });\n\n    // And this is what the DOM looks like\n    setTimeout(() => {\n      const res = document.querySelector('#App6 ul').textContent.match(/\\(\\d*\\)/g);\n      console.log('Actual order:   ' + res.join(','));\n    }, 100);\n  };\n\n  doDoubleMix = (e) => {\n    e && e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    shuffle(newItems);\n\n    // So this is the shuffled order\n    console.log('Expected order 1: ' + newItems.map((el) => '(' + el.val + ')').join(','));\n\n    this.setState({\n      items: newItems\n    });\n\n    setTimeout(() => {\n      var newItems2 = newItems.concat([]);\n      shuffle(newItems2);\n      this.setState({\n        items: newItems2\n      });\n      console.log('Expected order 2: ' + newItems2.map((el) => '(' + el.val + ')').join(','));\n    }, 1);\n\n    // And this is what the DOM looks like\n    setTimeout(() => {\n      const res = document.querySelector('#App6 ul').textContent.match(/\\(\\d*\\)/g);\n      console.log('Actual order:     ' + res.join(','));\n    }, 100);\n  };\n\n  doMoveOne = (e) => {\n    e && e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    newItems.push(newItems.shift());\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doClearMarkers = (e) => {\n    e && e.preventDefault();\n    const tmp = document.querySelectorAll('.debugMarker');\n    for (const marker of tmp) {\n      marker.parentNode.removeChild(marker);\n    }\n  };\n\n  componentDidMount() {\n    let i = 0;\n\n    while (this.items.length < 5) {\n      this.items[this.items.length] = { key: i, val: i };\n      i++;\n    }\n    this.setState({ items: this.items });\n  }\n\n  renderItem = (item, i) => {\n    if (this.props.useFunctionalComponent) {\n      return createElement(\n        FuncListItemMoveAnim,\n        { key: item.key, index: i, animation: this.props.animation, ...animMove, onClick: this.doMove },\n        `${item.val}bar (${item.key})`\n      );\n    } else {\n      return createElement(\n        ListItemMoveAnim,\n        { key: item.key, index: i, animation: this.props.animation, onClick: this.doMove },\n        `${item.val}bar (${item.key})`\n      );\n    }\n  };\n\n  render() {\n    return createElement('div', null, [\n      createElement('ul', null, this.state.items.map(this.renderItem)),\n      createElement('h2', null, 'Shuffle w. Anim'),\n      createElement('p', null, this.props.description),\n      createElement('button', { onClick: this.doAdd }, 'Add'),\n      createElement('button', { onClick: this.doMix }, 'Shuffle'),\n      createElement('button', { onClick: this.doDoubleMix }, 'DoubleShuffle'),\n      createElement('button', { onClick: this.doMoveOne }, 'Move 1'),\n      createElement('button', { onClick: this.doRemoveMix }, 'Remove' + (this.state.deleted ? ` (${this.state.deleted})` : '')),\n      createElement('button', { onClick: this.doClearMarkers }, 'Clear debug markers')\n    ]);\n  }\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  var container_1 = document.querySelector('#App1');\n  var container_2 = document.querySelector('#App2');\n  var container_3 = document.querySelector('#App3');\n  var container_4 = document.querySelector('#App4');\n  var container_5 = document.querySelector('#App5');\n  var container_6 = document.querySelector('#App6');\n\n  var useFunctionalComponent = location.search === '?functional';\n\n  render(\n    createElement(List, {\n      useFunctionalComponent,\n      animation: 'HeightAndFade',\n      description: 'The children in this container animate opacity and height when added and removed. Click an item to remove it.'\n    }),\n    container_1\n  );\n\n  render(\n    createElement(List, {\n      useFunctionalComponent,\n      animation: 'NoTranistionEvent',\n      description:\n        'The children in this container have a broken animation. This is detected by inferno-animation and the animation callback is called immediately. Click an item to remove it.'\n    }),\n    container_2\n  );\n\n  render(\n    createElement(MixedList, {\n      useFunctionalComponent,\n      animation: 'HeightAndFade',\n      description:\n        'This container fades in and blocks the children from animating on first render. There is no animation on divider between elements. When you click [Remove] a random row and another random divder will be removed. Click an item to remove it (leaving the divider).'\n    }),\n    container_3\n  );\n\n  render(\n    createElement(ShuffleList, {\n      useFunctionalComponent,\n      animation: 'HeightAndFade',\n      description: 'This container will shuffle keys or items. Click an item to remove it.'\n    }),\n    container_4\n  );\n\n  var btn = document.querySelector('#Rerender > button');\n  btn.addEventListener('click', (e) => {\n    e && e.preventDefault();\n    //render(createElement('div', null, createElement(RerenderList, {animation: 'HeightAndFade', items: 5})), container_5);\n    render(\n      createElement(RerenderList, {\n        useFunctionalComponent,\n        animation: 'HeightAndFade',\n        items: 5,\n        description: 'This container will be filled with 5 rows every time you click the button. Click an item to remove it.'\n      }),\n      container_5\n    );\n  });\n  render(\n    createElement(ShuffleListWithAnimation, {\n      useFunctionalComponent,\n      animation: 'MoveAnim',\n      description: 'This container will animate items on shuffle. Click an item to randomly move it.'\n    }),\n    container_6\n  );\n});\n"
  },
  {
    "path": "docs/animations/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <link href=\"./app.css\" rel=\"stylesheet\" />\n    <title>inferno-animation</title>\n    <script defer src=\"dist/bundle.js\" type=\"text/javascript\"></script>\n</head>\n  <body>\n    <h1>inferno-animation examples\n        <small><a href=\"index.html\">class components</a> | <a href=\"index.html?functional\">functional components</a></small></h1>\n    <div id=\"App1\" class=\"App\"></div>\n    <div id=\"App2\" class=\"App\"></div>\n    <div id=\"App3\" class=\"App\"></div>\n    <div id=\"App4\" class=\"App\"></div>\n    <div id=\"Rerender\" class=\"App\">\n      <div id=\"App5\"></div>\n      <button>Rerender</button>\n    </div>\n    <div id=\"App6\" class=\"App\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "docs/animations-demo/app.css",
    "content": "/* Using CSS-vars for transitions so you can experiment easily */\n:root {\n  --infernoAnimationEnter: all 1.2s ease-out;\n  --infernoAnimationLeave: all .6s ease-out;\n}\n\n/* These are used for <img> and .body transitions */\n.item {\n  --imgEnter: transform .5s ease-out, opacity 1s ease-in;\n  --imgLeave: transform .4s ease-in, opacity .4s ease-in;\n\n  --bodyEnter: transform .3s .5s ease-out, opacity 1s ease-in;\n  --bodyLeave: transform .2s ease-in, opacity .3s ease-in;\n}\n\n/*******************************************/\n/* Animate height and opacity of card <li> */\n/*******************************************/\n.Complex-leave {\n    /* Leave animation start state */\n    opacity: 1;\n    transform: translateX(0);\n}\n\n.Complex-leave-active {\n    /* Leave animation transitions */\n    overflow: visible;\n    transition: var(--infernoAnimationLeave);\n    pointer-events: none; /* prevent hover to fire transition events */\n}\n\n.Complex-leave-end {\n    /* Leave animation end state */\n    opacity: 0;\n    height: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    border-width: 0;\n    transform: translateX(100%);\n}\n\n.Complex-enter {\n    /* Enter animation start state */\n    opacity: 0.7;\n    height: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    border-width: 0;\n}\n\n.Complex-enter-active {\n    /* Enter animation transitions */\n    transition: var(--infernoAnimationEnter);\n    pointer-events: none; /* prevent hover to fire transition events */\n}\n\n.Complex-enter-end {\n    /* Enter animation end state */\n    opacity: 1;\n}\n\n/******************************/\n/* Animate avatar image <img> */\n/******************************/\n.Complex-leave img {\n  /* Leave animation start state */\n  opacity: 1;\n}\n\n.Complex-leave-active img {\n  /* Leave animation transitions */\n  overflow: hidden;\n  transition: var(--infernoAnimationLeave);\n}\n\n.Complex-leave-end img {\n  /* Leave animation end state */\n  opacity: 0;\n}\n\n.Complex-enter img {\n  /* Enter animation start state */\n  opacity: 0;\n  transform: translateX(-150%);\n}\n\n.Complex-enter-active img {\n  /* Enter animation transitions */\n  transition: var(--infernoAnimationEnter);\n}\n\n.Complex-enter-end img {\n  /* Enter animation end state */\n  opacity: 1;\n  transform: translateX(0);\n}\n\n.Complex-enter-end img {\n  /* Enter animation end state */\n  opacity: 1;\n  transform: translateX(0);\n}\n\n/***************************/\n/* Animate card body .body */\n/***************************/\n.Complex-leave .body {\n  /* Leave animation start state */\n  opacity: 1;\n}\n\n.Complex-leave-active .body {\n  /* Leave animation transitions */\n  overflow: hidden;\n  transition: var(--bodyLeave);\n}\n\n.Complex-leave-end .body {\n  /* Leave animation end state */\n  opacity: 0;\n  transform: translateX(150%);\n}\n\n.Complex-enter .body {\n  /* Enter animation start state */\n  opacity: 0;\n  transform: translateX(150%);\n}\n\n.Complex-enter-active .body {\n  /* Enter animation transitions */\n  transition: var(--bodyEnter);\n}\n\n.Complex-enter-end .body {\n  /* Enter animation end state */\n  opacity: 1;\n  transform: translateX(0);\n}\n\n/* Some CSS for the list and cards */\n\nul {\n  box-sizing: border-box;\n  margin: 0;\n  padding: 0;\n  list-style: none;\n  margin-bottom: 0.5rem;\n  width: 40rem;\n  max-width: 100%;\n}\n\nli {\n  box-sizing: border-box;\n  padding: 0.5rem 1rem;\n  background: #4A90E2;\n  color: white;\n  text-align: center;\n  border-top: 1px solid #fff;\n  overflow: hidden;\n}\n\nli:hover {\n  background: #3775bb;\n}\n\nli.item img {\n  background-color: #fff;\n  border-radius: 50%;\n  margin: 1rem;\n  height: auto;\n  width: auto;\n}\n\nli.item .inner {\n  display: flex;\n  flex-direction: row;\n  height: 8rem;\n}\n\nli.item .body {\n  padding: 0.5rem;\n  margin-right: 0.5rem;\n  min-height: 4em;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: flex-start;\n  flex-grow: 1;\n}\n\nli.item h2 {\n  color: white;\n  margin-bottom: 0;\n  font-weight: 400;\n}\n\n/* Some general CSS for the example */\n\nbutton {\n  padding: 0.5rem 1rem;\n  margin: 0.5rem auto 0;\n  display: block;\n  background: #35a748;\n  color: white;\n  border-style: none;\n  border-radius: 4px;\n  width: 10rem;\n} button:hover {\n  background: #3775bb;\n}\n\nbody {\n  font-family: helvetica;\n  box-sizing: border-box;\n  margin: 0;\n  padding: 1rem;\n  display: flex;\n  gap: 2rem;\n  justify-content: center;\n  align-items: flex-end;\n  height: 100vh;\n  overflow-y: scroll;\n  overflow-x: hidden;\n}\n\n.App {\n  box-sizing: border-box;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: flex-end;\n  padding: 1rem;\n}\n\nh1 {\n  transform: rotate(-90deg);\n  font-size: 2rem;\n  font-weight: 800;\n  color: #ddd;\n  text-align: center;\n  margin: 0.5rem;\n  white-space: nowrap;\n  width: 2rem;\n  transform-origin: 50% 50%;\n}\n\nh1 small {\n  font-size: 0.5em;\n}\nh1 small a {\n  color: #4A90E2;\n  text-decoration: none;\n}\nh1 small a:hover {\n  color: #3775bb;\n}\n\nh2 {\n  font-size: 1rem;\n  font-weight: 100;\n  color: #4A90E2;\n  text-align: center;\n}\n\nh3 {\n  font-size: 0.85rem;\n  font-weight: 100;\n}\n\np {\n  font-size: 0.85rem;\n  font-weight: 100;\n  color: #888;\n  text-align: center;\n  margin-top: -0.5em;\n  width: 40rem;\n  max-width: 100%;\n}\n"
  },
  {
    "path": "docs/animations-demo/app.js",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport { AnimatedComponent, componentDidAppear, componentWillDisappear } from 'inferno-animation';\n\nlet renderCounter = 0;\n\nconst anim = {\n  onComponentDidAppear: componentDidAppear,\n  onComponentWillDisappear: componentWillDisappear\n};\n\nclass ListItem extends AnimatedComponent {\n  render() {\n    renderCounter++;\n    return createElement(\n      'li',\n      {\n        className: 'item',\n        onClick: (e) => this.props.onClick(e, this.props.index)\n      },\n      createElement('div', { className: 'inner' }, [\n        createElement('img', { width: '120px', height: '120px', src: 'avatar.png' }),\n        createElement('div', { className: 'body' }, [\n          createElement('h2', null, this.props.children),\n          createElement('h3', null, 'Inferno is a blazingly fast framework.')\n        ])\n      ])\n    );\n  }\n}\n\nclass List extends Component {\n  constructor() {\n    super();\n\n    this.state = {\n      items: []\n    };\n    this.items = [];\n  }\n\n  doRemove = (e, index) => {\n    e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    newItems.splice(index, 1);\n    this.setState({\n      items: newItems\n    });\n  };\n\n  doAdd = (e) => {\n    e.preventDefault();\n    var newItems = this.state.items.concat([]);\n    var nextKey = newItems.length === 0 ? 0 : newItems[newItems.length - 1].key + 1;\n    newItems.push({ key: nextKey });\n    this.setState({\n      items: newItems\n    });\n  };\n\n  componentDidMount() {\n    let i = 0;\n\n    while (this.items.length < 20) {\n      this.items[this.items.length] = { key: i++ };\n    }\n    this.setState({ items: this.items });\n  }\n\n  renderItem = (item, i) => {\n    return createElement(\n      ListItem,\n      { key: item.key, index: i, animation: this.props.animation, onClick: this.doRemove },\n      `This line is nice with ${item.key + 1} bar`\n    );\n  };\n\n  render() {\n    return createElement('div', null, [\n      createElement('ul', null, this.state.items.map(this.renderItem)),\n      createElement('h2', null, this.props.animation),\n      createElement('p', null, this.props.description),\n      createElement('button', { onClick: this.doAdd }, 'Add')\n    ]);\n  }\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  var container_1 = document.querySelector('#App1');\n\n  render(\n    createElement(List, {\n      animation: 'Complex',\n      description:\n        'Each card <li> animates height and opacity on add. The image and body of each card animates using the card animation CSS-classes but with different transitions. The card inherits AnimatedComponet which is only aware of the card animation. The child animations need to be finished when the card animations are finished.'\n    }),\n    container_1\n  );\n});\n"
  },
  {
    "path": "docs/animations-demo/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <link href=\"./app.css\" rel=\"stylesheet\" />\n    <title>inferno-animation</title>\n    <script defer src=\"dist/bundle.js\" type=\"text/javascript\"></script>\n</head>\n  <body>\n    <h1>inferno-animation demo</h1>\n    <div id=\"App1\" class=\"App\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "docs/animations-demo-inner/app.css",
    "content": "/* Using CSS-vars for transitions so you can experiment easily */\n:root {\n  --infernoAnimationEnter: all 1.2s ease-out;\n  --infernoAnimationLeave: all .6s ease-out;\n}\n\n/*******************************************/\n/* Animate height and opacity of card <li> */\n/*******************************************/\n.inner-leave {\n    /* Leave animation start state */\n    opacity: 1;\n    transform: translateX(0);\n}\n\n.inner-leave-active {\n    /* Leave animation transitions */\n    overflow: visible;\n    transition: var(--infernoAnimationLeave);\n    pointer-events: none; /* prevent hover to fire transition events */\n}\n\n.inner-leave-end {\n    /* Leave animation end state */\n    opacity: 0;\n    transform: translateX(-100%);\n}\n\n.inner-enter {\n    /* Enter animation start state */\n    opacity: 0.5  ;\n    transform: translateX(50%);\n}\n\n.inner-enter-active {\n    /* Enter animation transitions */\n    transition: var(--infernoAnimationEnter);\n    pointer-events: none; /* prevent hover to fire transition events */\n}\n\n.inner-enter-end {\n    /* Enter animation end state */\n    opacity: 1;\n    transform: translateX(0);\n}\n\n\n/* Some CSS for the list and cards */\n.page {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}\n\n.page img {\n  margin: 20vh auto 0;\n  display: block;\n  background-color: white;\n}\n\n.page h3 {\n  background-color: white;\n  margin: 1rem;\n  text-align: center;\n}\n\n.page p {\n  background-color: white;\n  margin: 1rem auto;\n  max-width: 20rem;\n  text-align: left;\n}\n\n.inner {\n  max-width: 30rem;\n  margin: 10vh auto 2rem;\n  padding: 4rem;\n  background-color: #eee;\n}\n\n.inner h2 {\n  font-size: 3em;\n  margin: 3rem auto;\n  text-align: center;\n}\n\n/* Some general CSS for the example */\n\nbutton {\n  padding: 0.5rem 1rem;\n  margin: 0.5rem auto 0;\n  display: block;\n  background: #35a748;\n  color: white;\n  border-style: none;\n  border-radius: 4px;\n  width: 10rem;\n} button:hover {\n  background: #3775bb;\n}\n\nbody {\n  font-family: helvetica;\n  box-sizing: border-box;\n  margin: 0;\n  padding: 1rem;\n  display: flex;\n  gap: 2rem;\n  justify-content: center;\n  align-items: flex-end;\n  height: 100vh;\n  overflow-y: scroll;\n  overflow-x: hidden;\n}\n\n.App {\n  box-sizing: border-box;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: flex-end;\n  padding: 1rem;\n  width: calc(100vw - 2rem);\n  height: 100vh;\n}\n\nh1 {\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  transform: rotate(-90deg);\n  font-size: 2rem;\n  font-weight: 800;\n  color: #ddd;\n  text-align: center;\n  margin: 0.5rem;\n  white-space: nowrap;\n  width: 2rem;\n  transform-origin: 50% 50%;\n}\n\nh1 small {\n  font-size: 0.5em;\n}\nh1 small a {\n  color: #4A90E2;\n  text-decoration: none;\n}\nh1 small a:hover {\n  color: #3775bb;\n}\n\nh2 {\n  font-size: 1rem;\n  font-weight: 100;\n  color: #4A90E2;\n  text-align: center;\n}\n\nh3 {\n  font-size: 0.85rem;\n  font-weight: 100;\n}\n\np {\n  font-size: 0.85rem;\n  font-weight: 100;\n  color: #888;\n  text-align: center;\n  margin-top: -0.5em;\n  width: 40rem;\n  max-width: 100%;\n}\n"
  },
  {
    "path": "docs/animations-demo-inner/app.js",
    "content": "import { Component, render, createRef } from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport { componentDidAppear, componentWillDisappear } from 'inferno-animation';\n\nclass Page extends Component {\n  componentDidAppear(dom) {\n    // We need to store a reference to the animating child that\n    // isn't removed on unmount. Currently, this requires passing\n    // a ref as property and referencing the .current property\n    // of that object.\n    this._innerEl = this.props.innerRef.current;\n    componentDidAppear(this._innerEl, { animation: 'inner' });\n  }\n\n  componentWillDisappear(dom, callback) {\n    componentWillDisappear(this._innerEl, { animation: 'inner' }, callback);\n  }\n\n  render() {\n    return createElement(\n      'div',\n      {\n        className: 'page'\n      },\n      createElement('div', { className: 'random-wrapper' }, [\n        createElement('h3', null, 'Page ' + this.props.step),\n        createElement('img', { width: '120px', height: '120px', src: 'avatar.png' }),\n        createElement('p', null, 'The entire page is swapped, but we are only animating div.inner. This gives the apperance of only swapping the box below.'),\n        createElement(\n          'p',\n          null,\n          \"In order not to hide the incoming content we can't set background on div.page. The background needs to be provided by a backdrop in the wizard component.\"\n        ),\n        createElement('div', { ref: this.props.innerRef, className: 'inner' }, [\n          createElement('h2', null, 'Step ' + this.props.step),\n          createElement(\n            'button',\n            {\n              onClick: (e) => {\n                e.preventDefault();\n                this.props.onNext();\n              }\n            },\n            'Next'\n          )\n        ])\n      ])\n    );\n  }\n}\n\nconst nrofSteps = 3;\n\nclass Wizard extends Component {\n  constructor() {\n    super();\n\n    // Ref objects used to reference the animating children of each page\n    this._innerAnimRefs = [];\n    for (let i = 0; i < nrofSteps; i++) {\n      this._innerAnimRefs.push(createRef());\n    }\n\n    this.state = {\n      showStepIndex: 0\n    };\n  }\n\n  doGoNext = () => {\n    this.setState({\n      showStepIndex: (this.state.showStepIndex + 1) % nrofSteps\n    });\n  };\n\n  render() {\n    const { showStepIndex } = this.state;\n\n    return createElement(Page, { key: 'page_' + showStepIndex, step: showStepIndex + 1, innerRef: this._innerAnimRefs[showStepIndex], onNext: this.doGoNext });\n  }\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  var container_1 = document.querySelector('#App1');\n\n  render(createElement(Wizard), container_1);\n});\n"
  },
  {
    "path": "docs/animations-demo-inner/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <link href=\"./app.css\" rel=\"stylesheet\" />\n    <title>inferno-animation</title>\n    <script defer src=\"dist/bundle.js\" type=\"text/javascript\"></script>\n</head>\n  <body>\n    <h1>inferno-animation demo animation of child</h1>\n    <div id=\"App1\" class=\"App\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "docs/animations-global-demo/app.css",
    "content": "/* Using CSS-vars for transitions so you can experiment easily */\n:root {\n  --infernoAnimationEnter: all 0.3s ease-out;\n  --infernoAnimationLeave: all 0s;\n}\n\n/******************************/\n/* Animate avatar image <img> */\n/******************************/\n.AnimateLogo-enter-active {\n  /* Enter animation transitions */\n  transition: var(--infernoAnimationEnter);\n}\n\n/* Some general CSS for the example */\n\nbutton {\n  padding: 0.5rem 1rem;\n  margin: 0.5rem auto 0;\n  display: block;\n  background: #35a748;\n  color: white;\n  border-style: none;\n  border-radius: 4px;\n  width: 10rem;\n} button:hover {\n  background: #3775bb;\n}\n\nbody {\n  font-family: helvetica;\n  box-sizing: border-box;\n  margin: 0;\n  padding: 1rem;\n  display: flex;\n  gap: 2rem;\n  justify-content: center;\n  align-items: flex-end;\n  height: 100vh;\n  overflow-y: scroll;\n  overflow-x: hidden;\n}\n\n.Page {\n  position: absolute;\n  top: 0;\n  left: 0;\n}\n\n.App {\n  box-sizing: border-box;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: flex-end;\n  padding: 1rem;\n}\n\nh1 {\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  transform: rotate(-90deg);\n  font-size: 2rem;\n  font-weight: 800;\n  color: #ddd;\n  text-align: center;\n  margin: 0.5rem;\n  white-space: nowrap;\n  width: 2rem;\n  transform-origin: 50% 50%;\n}\n\nh1 small {\n  font-size: 0.5em;\n}\n\n\nh2 {\n  font-size: 1rem;\n  font-weight: 100;\n  color: #4A90E2;\n  text-align: center;\n}\n\n.Page {\n  width: 100vw;\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n}\n\n.Menu {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  gap: 1rem;\n  height: 8rem;\n  flex-grow: 0;\n  flex-shrink: 0;\n  border-bottom: 1px solid #ddd;\n}\n\nimg {\n  width: 100%;\n  height: 100%;\n}\n\n.Menu .logo {\n  width: 8rem;\n  height: 8rem;\n  transform: translateZ(0);\n}\n.Menu .body {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  flex-grow: 1;\n  flex-shrink: 1;\n}\n.Menu .body h3 {\n  flex-grow: 0;\n  flex-shrink: 0;\n  margin-left: auto;\n  margin-right: 2rem;\n  text-align: right;\n  width: 6em;\n}\n\n.content {\n  height: 100%;\n  flex-grow: 1;\n  flex-shrink: 1;\n}\n\n.Hero {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n}\n\n.Hero .logo {\n  width: 30rem;\n  height: 30rem;\n  transform: translateZ(0);\n}\n\n.payoff {\n  transform: translateZ(0);\n}"
  },
  {
    "path": "docs/animations-global-demo/app.js",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport { componentDidAppear, componentWillDisappear } from 'inferno-animation';\n\nconst anim = {\n  onComponentDidAppear: componentDidAppear,\n  onComponentWillDisappear: componentWillDisappear\n};\n\nfunction Logo() {\n  return createElement('div', { className: 'logo' }, createElement('img', { width: '120px', height: '120px', src: 'inferno-logo.svg' }));\n}\nLogo.defaultHooks = anim;\n\nfunction Payoff() {\n  return createElement('h2', { className: 'payoff' }, 'Inferno is a blazingly fast framework.');\n}\nPayoff.defaultHooks = anim;\n\nfunction PageOne({ onClick }) {\n  return createElement('div', { className: 'Page' }, [\n    createElement('div', { className: 'Menu' }, createElement('div', { className: 'body' }, [createElement('h3', null, 'Page 1')])),\n    createElement('div', { className: 'content' }, [\n      createElement('div', { className: 'Hero' }, [\n        createElement(Logo, { globalAnimationKey: 'main-logo', animation: 'AnimateLogo' }),\n        createElement(Payoff, { globalAnimationKey: 'payoff', animation: 'AnimateLogo' })\n      ]),\n      createElement('button', { onClick, children: 'Click here' })\n    ])\n  ]);\n}\n\nfunction PageTwo({ onClick }) {\n  return createElement('div', { className: 'Page' }, [\n    createElement('div', { className: 'Menu' }, [\n      createElement(Logo, { globalAnimationKey: 'main-logo', animation: 'AnimateLogo' }),\n      createElement('div', { className: 'body' }, [\n        createElement(Payoff, { globalAnimationKey: 'payoff', animation: 'AnimateLogo' }),\n        createElement('h3', null, 'Page 2')\n      ])\n    ]),\n    createElement('div', { className: 'content' }, [createElement('button', { onClick, children: 'Click here' })])\n  ]);\n}\n\nclass App extends Component {\n  constructor() {\n    super();\n\n    this.state = {\n      page: 0\n    };\n\n    this.didClick = this.didClick.bind(this);\n  }\n\n  didClick(e) {\n    e.preventDefault();\n    this.setState({\n      page: ++this.state.page % 2\n    });\n  }\n\n  render() {\n    return createElement(\n      'div',\n      null,\n      this.state.page === 0 ? createElement(PageOne, { onClick: this.didClick }) : createElement(PageTwo, { onClick: this.didClick })\n    );\n  }\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  var container_1 = document.querySelector('#App1');\n\n  render(\n    createElement(App, {\n      description:\n        'Each card <li> animates height and opacity on add. The image and body of each card animates using the card animation CSS-classes but with different transitions. The card inherits AnimatedComponet which is only aware of the card animation. The child animations need to be finished when the card animations are finished.'\n    }),\n    container_1\n  );\n});\n"
  },
  {
    "path": "docs/animations-global-demo/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <link href=\"./app.css\" rel=\"stylesheet\" />\n    <title>inferno-animation</title>\n    <script defer src=\"dist/bundle.js\" type=\"text/javascript\"></script>\n</head>\n  <body>\n    <h1>inferno-animation global animations</h1>\n    <div id=\"App1\" class=\"App\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "docs/async-render/app.js",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\nlet renderCounter = 0;\n\nclass ListItem extends Component {\n  render() {\n    renderCounter++;\n    return createElement('li', null, this.props.children);\n  }\n}\n\nclass List extends Component {\n  constructor() {\n    super();\n    // set initial time:\n    this.state = {\n      items: []\n    };\n    this.items = [];\n  }\n\n  componentDidMount() {\n    let i = 0;\n\n    while (this.items.length < 2000) {\n      this.items[this.items.length] = createElement(ListItem, { key: ++i }, `${this.items.length}bar`);\n      this.setState({ items: this.items });\n    }\n  }\n\n  render() {\n    return createElement('ul', null, this.state.items);\n  }\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  var container = document.querySelector('#App');\n\n  const times = [];\n  const count = 2;\n  let totalTime = 0;\n\n  for (var i = 0; i < count; i++) {\n    render(createElement(List), container);\n  }\n\n  setTimeout(function () {\n    render(\n      createElement(\n        'div',\n        null,\n        `\n      Rounds: ${count},\n      Average: ${totalTime / count},\n      Total: ${totalTime},\n      counter: ${renderCounter}\n    `\n      ),\n      container\n    );\n  }, 5000);\n});\n"
  },
  {
    "path": "docs/async-render/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Async Render: Inferno</title>\n</head>\n<body>\n<div id=\"App\"></div>\n<script src=\"dist/bundle.js\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/build.js",
    "content": "import {rollup} from \"rollup\";\nimport { existsSync, readdirSync, statSync } from \"fs\";\nimport commonjsPlugin from \"@rollup/plugin-commonjs\";\nimport nodeResolvePlugin from \"@rollup/plugin-node-resolve\";\nimport { dirname, join, resolve } from \"path\";\nimport replace from \"@rollup/plugin-replace\";\nimport terser from '@rollup/plugin-terser';\nimport alias from \"@rollup/plugin-alias\";\nimport { fileURLToPath } from \"url\";\nimport babel from \"@rollup/plugin-babel\";\n\nconst isProduction = process.env.NODE_ENV === 'production';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst benchmarks = readdirSync(__dirname).filter(file => statSync(join(__dirname, file)).isDirectory());\nconst resolvePkg = pkg => resolve(__dirname, '../packages', pkg, 'dist', 'index.mjs');\n\n\nconsole.log(resolvePkg('inferno'));\n\n// see below for details on the options\nconst plugins = [\n  replace({\n    preventAssignment: true,\n    'process.env.NODE_ENV': '\"production\"',\n    sourcemap: false\n  }),\n  nodeResolvePlugin({\n    preferBuiltins: false\n  }),\n  babel({\n    exclude: 'node_modules/**',\n    sourceMaps: false,\n    babelrc: false,\n    presets: [['@babel/env', {loose: true, modules: false}]],\n    plugins: [\n      ['babel-plugin-inferno', {imports: true, defineAllArguments: true}],\n      [\"@babel/plugin-proposal-class-properties\", { \"loose\": true }]\n    ]\n  }),\n  commonjsPlugin({\n    sourceMap: false\n  }),\n  alias({\n    resolve: ['.js'],\n    entries: [\n      {find: 'inferno', replacement: resolvePkg('inferno')},\n      {find: 'inferno-animation', replacement: resolvePkg('inferno-animation')},\n      {find: 'inferno-compat', replacement: resolvePkg('inferno-compat')},\n      {find: 'inferno-create-element', replacement: resolvePkg('inferno-create-element')},\n      {find: 'inferno-hydrate', replacement: resolvePkg('inferno-hydrate')},\n      {find: 'inferno-extras', replacement: resolvePkg('inferno-extras')},\n      {find: 'inferno-hyperscript', replacement: resolvePkg('inferno-hyperscript')},\n      {find: 'inferno-mobx', replacement: resolvePkg('inferno-mobx')},\n      {find: 'inferno-redux', replacement: resolvePkg('inferno-redux')},\n      {find: 'inferno-router', replacement: resolvePkg('inferno-router')},\n      {find: 'inferno-server', replacement: resolvePkg('inferno-server')},\n      {find: 'inferno-shared', replacement: resolvePkg('inferno-shared')},\n      {find: 'inferno-test-utils', replacement: resolvePkg('inferno-test-utils')},\n      {find: 'inferno-vnode-flags', replacement: resolvePkg('inferno-vnode-flags')},\n      {find: 'inferno-clone-vnode', replacement: resolvePkg('inferno-clone-vnode')},\n      {find: 'mobx', replacement: join(__dirname, '../node_modules/mobx/dist/mobx.esm.js')},\n      {find: 'perf-monitor', replacement: join(__dirname, '../node_modules/perf-monitor/dist/index.js')}\n    ]\n  })\n];\n\nif (isProduction) {\n  plugins.push(\n    terser({\n      compress: {\n        ecma: 5,\n        inline: true,\n        if_return: false,\n        reduce_funcs: false,\n        passes: 5,\n        comparisons: false,\n      },\n      ie8: false,\n      mangle: {\n        toplevel: true\n      },\n      parse: {\n        html5_comments: false,\n        shebang: false\n      },\n      toplevel: false,\n      warnings: false\n    })\n  );\n}\n\nfor (const dir of benchmarks) {\n  const benchmarkPath = join(__dirname, dir);\n  const appJsPath = resolve(benchmarkPath, 'app.js')\n\n  // Don't build examples that don't have app.js\n  if (!existsSync(appJsPath)) continue;\n\n  const inputOptions = {\n    input: appJsPath,\n    plugins: plugins\n  };\n\n  const start = new Date();\n\n  console.log(`Build started -- ${start}`);\n\n  rollup(inputOptions).then(function (opts) {\n    return opts.write({\n      format: 'iife',\n      file: join(benchmarkPath, 'dist', 'bundle.js'),\n      sourcemap: false,\n      name: 'inferno'\n    });\n  });\n}\n"
  },
  {
    "path": "docs/compat/app.js",
    "content": "'use strict';\nimport { render, Component } from 'inferno-compat';\nimport { createElement } from 'inferno-create-element';\nvar h = createElement;\n\n/*\n Example of using context and setState callback function\n */\n\nfunction checkParams(state, props, context) {\n  console.log(state, props, context);\n}\n\nclass Button extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      btnstate: 'btnstate'\n    };\n  }\n\n  click() {\n    this.setState(checkParams);\n  }\n\n  render() {\n    return h(\n      'button',\n      {\n        onClick: this.click.bind(this),\n        style: { background: this.context.color }\n      },\n      this.props.children\n    );\n  }\n}\n\nclass Message extends Component {\n  render() {\n    return h('div', null, [this.props.text, h(Button, { buttonProp: 'magic' }, 'btn')]);\n  }\n}\n\nclass MessageList extends Component {\n  getChildContext() {\n    return { color: 'purple' };\n  }\n\n  render() {\n    const children = this.props.messages.map(function (message) {\n      return h(Message, { text: message.text });\n    });\n\n    return h('div', null, children);\n  }\n}\n\nrender(h(MessageList, { messages: [{ text: 'first' }, { text: 'second' }] }), document.getElementById('app1'));\n\nlet testValue = 11;\nfunction changeTestValue(event) {\n  testValue = event.target.value;\n\n  console.log(event.type, testValue);\n\n  renderLabels();\n}\n\nfunction renderLabels() {\n  render(\n    h('div', null, [\n      h('label', { for: 'test' }, [\n        'label for input',\n        h('input', {\n          id: 'test',\n          name: 'testing_radio',\n          value: 'first',\n          onChange: changeTestValue,\n          type: 'radio',\n          pattern: '[0-9]+([,.][0-9]+)?',\n          inputMode: 'numeric'\n        })\n      ]),\n      h('label', { for: 'test2' }, [\n        'label for input2',\n        h('input', {\n          id: 'test2',\n          name: 'testing_radio',\n          value: 'second',\n          onChange: changeTestValue,\n          type: 'radio',\n          pattern: '[0-9]+([,.][0-9]+)?',\n          inputMode: 'numeric'\n        })\n      ]),\n      h('label', { htmlFor: 'test3' }, [\n        'label for input3',\n        h('input', {\n          id: 'test3',\n          name: 'test3',\n          value: testValue,\n          onChange: changeTestValue,\n          type: 'number',\n          pattern: '[0-9]+([,.][0-9]+)?',\n          inputMode: 'numeric'\n        })\n      ])\n    ]),\n    document.getElementById('app2')\n  );\n}\nrenderLabels();\n\n// Cursor should not move ....\nclass NameForm extends Component {\n  constructor(props) {\n    super(props);\n    this.state = { value: 'ASYNC', radio: 'first', text: 'f', selectValue: 'second' };\n\n    this.handleChange = this.handleChange.bind(this);\n    this.radioChange = this.radioChange.bind(this);\n    this.textChange = this.textChange.bind(this);\n    this.selectChange = this.selectChange.bind(this);\n  }\n\n  handleChange(event) {\n    this.setState({ value: event.target.value });\n  }\n\n  radioChange(event) {\n    this.setState({ radio: event.target.value });\n  }\n\n  textChange(event) {\n    this.setState({ text: event.target.value });\n  }\n\n  selectChange(event) {\n    this.setState({ selectValue: event.target.value });\n  }\n\n  render() {\n    return h('div', null, [\n      h('label', { for: 'testasync' }, [\n        'async label for input',\n        h('input', {\n          id: 'testasync',\n          name: 'testing_radio_async',\n          value: 'first',\n          onClick: this.radioChange,\n          checked: this.state.radio === 'first',\n          type: 'radio'\n        })\n      ]),\n      h('label', { for: 'test2async' }, [\n        'async label for input2',\n        h('input', {\n          id: 'test2async',\n          name: 'testing_radio_async',\n          value: 'second',\n          onClick: this.radioChange,\n          checked: this.state.radio === 'second',\n          type: 'radio'\n        })\n      ]),\n      h('label', { htmlFor: 'test3as' }, [\n        'Async Name',\n        h('input', {\n          id: 'test3as',\n          name: 'test3as',\n          value: this.state.value,\n          onInput: this.handleChange,\n          type: 'text'\n        })\n      ]),\n      h('label', { htmlFor: 'textarea_async' }, [\n        'async texxt',\n        h('textarea', {\n          id: 'textarea_async',\n          name: 'textarea_async',\n          value: this.state.text,\n          onInput: this.textChange\n        })\n      ]),\n      h(\n        'select',\n        {\n          onChange: this.selectChange,\n          value: this.state.selectValue\n        },\n        [\n          h('option', {\n            value: 'first',\n            children: 'first'\n          }),\n          h('option', {\n            value: 'second',\n            children: 'second'\n          }),\n          h('option', {\n            value: 'third',\n            children: 'third'\n          })\n        ]\n      )\n    ]);\n  }\n}\n\nlet hoisted = h('input', {\n  id: 'test3sync',\n  name: 'test3sync',\n  value: '100',\n  type: 'text'\n});\nlet i = 0;\n// Cursor should not move ....\nclass NameForm2 extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      value: 'SYNC',\n      radio: 'first',\n      text: 'f',\n      selectValue: 'second'\n    };\n\n    this.handleChange = this.handleChange.bind(this);\n    this.radioChange = this.radioChange.bind(this);\n    this.textChange = this.textChange.bind(this);\n    this.selectChange = this.selectChange.bind(this);\n  }\n\n  handleChange(event) {\n    hoisted.props.value = 200;\n    this.setState({ value: event.target.value });\n  }\n\n  radioChange(event) {\n    this.setState({ radio: event.target.value });\n  }\n\n  textChange(event) {\n    this.setState({ text: event.target.value });\n  }\n\n  selectChange(event) {\n    this.setState({ selectValue: event.target.value });\n  }\n\n  render() {\n    return h('div', null, [\n      h('label', { for: 'testsync' }, [\n        'sync label for input',\n        h('input', {\n          id: 'testsync',\n          name: 'testing_radio_sync',\n          value: 'first',\n          onClick: this.radioChange,\n          checked: this.state.radio === 'first',\n          type: 'radio'\n        })\n      ]),\n      h('label', { for: 'test2sync' }, [\n        'sync label for input2',\n        h('input', {\n          id: 'test2sync',\n          name: 'testing_radio_sync',\n          value: 'second',\n          onClick: this.radioChange,\n          checked: this.state.radio === 'second',\n          type: 'radio'\n        })\n      ]),\n      h('label', { htmlFor: 'test3sync' }, [\n        'sync Name',\n        h('input', {\n          id: 'test3sync',\n          name: 'test3sync',\n          value: this.state.value,\n          onInput: this.handleChange,\n          type: 'text'\n        })\n      ]),\n      h('label', { htmlFor: 'textarea_sync' }, [\n        'sync text',\n        h('textarea', {\n          id: 'textarea_sync',\n          name: 'textarea_sync',\n          value: this.state.text,\n          onInput: this.textChange\n        })\n      ]),\n      h(\n        'select',\n        {\n          onChange: this.selectChange,\n          value: this.state.selectValue\n        },\n        [\n          h('option', {\n            value: 'first',\n            children: 'first'\n          }),\n          h('option', {\n            value: 'second',\n            children: 'second'\n          }),\n          h('option', {\n            value: 'third',\n            children: 'third'\n          })\n        ]\n      )\n    ]);\n  }\n}\n\n// render an instance of Clock into <body>:\nrenderLabels(h(NameForm, {}), document.getElementById('app3'));\nrenderLabels(h(NameForm2, {}), document.getElementById('app4'));\n"
  },
  {
    "path": "docs/compat/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Events test page</title>\n    <style>\n        .box {\n            padding: 50px;\n            width: 300px;\n            margin: 50px;\n            background: #d2eaff;\n            float: left;\n        }\n\n        label {\n            float: left;\n            width: 100%;\n        }\n    </style>\n</head>\n<body>\n<div class=\"box\" id=\"app\"></div>\n<div class=\"box\" id=\"app1\"></div>\n<div class=\"box\" id=\"app2\"></div>\n<div class=\"box\" id=\"app3\"></div>\n<div class=\"box\" id=\"app4\"></div>\n<script>\n    window.process = {\n        env: {\n            NODE_ENV: 'development'\n        }\n    };\n</script>\n<script src=\"dist/bundle.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/dbmonster/ENV.js",
    "content": "var ENV = ENV || (function () {\n\t\"use strict\";\n\n\tvar first = true;\n\tvar counter = 0;\n\tvar data;\n\tvar _base;\n\t(_base = String.prototype).lpad || (_base.lpad = function (padding, toLength) {\n\t\treturn padding.repeat((toLength - this.length) / padding.length).concat(this);\n\t});\n\n\tfunction formatElapsed(value) {\n\t\tvar comps;\n\n\t\tif (value > 60) {\n\t\t\tcomps = (value % 60).toFixed(2).split('.');\n\n\t\t\treturn Math.floor(value / 60) + \":\" + comps[0].lpad('0', 2) + \".\" + comps[1];\n\t\t}\n\n\t\treturn parseFloat(value).toFixed(2);\n\t}\n\n\tfunction getElapsedClassName(elapsed) {\n\t\tvar className = 'Query elapsed';\n\t\tif (elapsed >= 10.0) {\n\t\t\tclassName += ' warn_long';\n\t\t}\n\t\telse if (elapsed >= 1.0) {\n\t\t\tclassName += ' warn';\n\t\t}\n\t\telse {\n\t\t\tclassName += ' short';\n\t\t}\n\t\treturn className;\n\t}\n\n\tfunction countClassName(queries) {\n\t\tvar countClassName = \"label\";\n\t\tif (queries >= 20) {\n\t\t\tcountClassName += \" label-important\";\n\t\t}\n\t\telse if (queries >= 10) {\n\t\t\tcountClassName += \" label-warning\";\n\t\t}\n\t\telse {\n\t\t\tcountClassName += \" label-success\";\n\t\t}\n\t\treturn countClassName;\n\t}\n\n\tfunction updateQuery(object) {\n\t\tif (!object) {\n\t\t\tobject = {};\n\t\t}\n\t\tvar elapsed = Math.random() * 15;\n\t\tobject.elapsed = elapsed;\n\t\tobject.formatElapsed = formatElapsed(elapsed);\n\t\tobject.elapsedClassName = getElapsedClassName(elapsed);\n\t\tobject.query = \"SELECT blah FROM something\";\n\t\tobject.waiting = Math.random() < 0.5;\n\t\tif (Math.random() < 0.2) {\n\t\t\tobject.query = \"<IDLE> in transaction\";\n\t\t}\n\t\tif (Math.random() < 0.1) {\n\t\t\tobject.query = \"vacuum\";\n\t\t}\n\t\treturn object;\n\t}\n\n\tfunction cleanQuery(value) {\n\t\tif (value) {\n\t\t\tvalue.formatElapsed = \"\";\n\t\t\tvalue.elapsedClassName = \"\";\n\t\t\tvalue.query = \"\";\n\t\t\tvalue.elapsed = null;\n\t\t\tvalue.waiting = null;\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tquery: \"***\",\n\t\t\t\tformatElapsed: \"\",\n\t\t\t\telapsedClassName: \"\"\n\t\t\t};\n\t\t}\n\t}\n\n\tfunction generateRow(object, keepIdentity, counter) {\n\t\tvar nbQueries = Math.floor((Math.random() * 10) + 1);\n\t\tif (!object) {\n\t\t\tobject = {};\n\t\t}\n\t\tobject.lastMutationId = counter;\n\t\tobject.nbQueries = nbQueries;\n\t\tif (!object.lastSample) {\n\t\t\tobject.lastSample = {};\n\t\t}\n\t\tif (!object.lastSample.topFiveQueries) {\n\t\t\tobject.lastSample.topFiveQueries = [];\n\t\t}\n\t\tif (keepIdentity) {\n\t\t\t// for Angular optimization\n\t\t\tif (!object.lastSample.queries) {\n\t\t\t\tobject.lastSample.queries = [];\n\t\t\t\tfor (var l = 0; l < 12; l++) {\n\t\t\t\t\tobject.lastSample.queries[l] = cleanQuery();\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (var j in object.lastSample.queries) {\n\t\t\t\tvar value = object.lastSample.queries[j];\n\t\t\t\tif (j <= nbQueries) {\n\t\t\t\t\tupdateQuery(value);\n\t\t\t\t} else {\n\t\t\t\t\tcleanQuery(value);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tobject.lastSample.queries = [];\n\t\t\tfor (var j = 0; j < 12; j++) {\n\t\t\t\tif (j < nbQueries) {\n\t\t\t\t\tvar value = updateQuery(cleanQuery());\n\t\t\t\t\tobject.lastSample.queries.push(value);\n\t\t\t\t} else {\n\t\t\t\t\tobject.lastSample.queries.push(cleanQuery());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (var i = 0; i < 5; i++) {\n\t\t\tvar source = object.lastSample.queries[i];\n\t\t\tobject.lastSample.topFiveQueries[i] = source;\n\t\t}\n\t\tobject.lastSample.nbQueries = nbQueries;\n\t\tobject.lastSample.countClassName = countClassName(nbQueries);\n\t\treturn object;\n\t}\n\n\tfunction getData(keepIdentity) {\n\t\tvar oldData = data;\n\t\tif (!keepIdentity) { // reset for each tick when !keepIdentity\n\t\t\tdata = [];\n\t\t\tfor (var i = 1; i <= ENV.rows; i++) {\n\t\t\t\tdata.push({ dbname: 'cluster' + i, query: \"\", formatElapsed: \"\", elapsedClassName: \"\" });\n\t\t\t\tdata.push({ dbname: 'cluster' + i + ' replica', query: \"\", formatElapsed: \"\", elapsedClassName: \"\" });\n\t\t\t}\n\t\t}\n\t\tif (!data) { // first init when keepIdentity\n\t\t\tdata = [];\n\t\t\tfor (var i = 1; i <= ENV.rows; i++) {\n\t\t\t\tdata.push({ dbname: 'cluster' + i });\n\t\t\t\tdata.push({ dbname: 'cluster' + i + ' replica' });\n\t\t\t}\n\t\t\toldData = data;\n\t\t}\n\t\tfor (var i in data) {\n\t\t\tvar row = data[i];\n\t\t\tif (!keepIdentity && oldData && oldData[i]) {\n\t\t\t\trow.lastSample = oldData[i].lastSample;\n\t\t\t}\n\t\t\tif (!row.lastSample || Math.random() < ENV.mutations()) {\n\t\t\t\tcounter = counter + 1;\n\t\t\t\tif (!keepIdentity) {\n\t\t\t\t\trow.lastSample = null;\n\t\t\t\t}\n\t\t\t\tgenerateRow(row, keepIdentity, counter);\n\t\t\t} else {\n\t\t\t\tdata[i] = oldData[i];\n\t\t\t}\n\t\t}\n\t\tfirst = false;\n\t\treturn {\n\t\t\ttoArray: function () {\n\t\t\t\treturn data;\n\t\t\t}\n\t\t};\n\t}\n\n\tvar mutationsValue = 0.5;\n\n\tfunction mutations(value) {\n\t\tif (value) {\n\t\t\tmutationsValue = value;\n\t\t\treturn mutationsValue;\n\t\t} else {\n\t\t\treturn mutationsValue;\n\t\t}\n\t}\n\n\tvar body = document.querySelector('body');\n\tvar theFirstChild = body.firstChild;\n\n\tvar sliderContainer = document.createElement('div');\n\tsliderContainer.style.cssText = \"display: flex\";\n\tvar slider = document.createElement('input');\n\tvar text = document.createElement('label');\n\ttext.innerHTML = 'mutations : ' + (mutationsValue * 100).toFixed(0) + '%';\n\ttext.id = \"ratioval\";\n\tslider.setAttribute(\"type\", \"range\");\n\tslider.style.cssText = 'margin-bottom: 10px; margin-top: 5px';\n\tslider.addEventListener('change', function (e) {\n\t\tENV.mutations(e.target.value / 100);\n\t\tdocument.querySelector('#ratioval').innerHTML = 'mutations : ' + (ENV.mutations() * 100).toFixed(0) + '%';\n\t});\n\tsliderContainer.appendChild(text);\n\tsliderContainer.appendChild(slider);\n\tbody.insertBefore(sliderContainer, theFirstChild);\n\n\treturn {\n\t\tgenerateData: getData,\n\t\trows: 50,\n\t\ttimeout: 0,\n\t\tmutations: mutations\n\t};\n})();\n"
  },
  {
    "path": "docs/dbmonster/app.js",
    "content": "// import { startFPSMonitor, startMemMonitor, initProfiler, startProfile, endProfile } from 'perf-monitor';\nimport { createVNode, render } from 'inferno';\n\nvar elem = document.getElementById('app');\n\n// startFPSMonitor();\n// startMemMonitor();\n// initProfiler('view update');\n\nfunction renderBenchmark(dbs) {\n  var length = dbs.length;\n  var databases = [];\n\n  for (var i = 0; i < length; i++) {\n    var db = dbs[i];\n    var lastSample = db.lastSample;\n    var children = [\n      createVNode(1, 'td', 'dbname', db.dbname, 16, null, null, null),\n      createVNode(1, 'td', 'query-count', createVNode(1, 'span', lastSample.countClassName, lastSample.nbQueries, 16, null, null, null), 2, null, null, null)\n    ];\n\n    for (var i2 = 0; i2 < 5; i2++) {\n      var query = lastSample.topFiveQueries[i2];\n\n      children.push(\n        createVNode(\n          1,\n          'td',\n          query.elapsedClassName,\n          [\n            createVNode(1, 'div', null, query.formatElapsed, 16, null, null, null),\n            createVNode(\n              1,\n              'div',\n              'popover left',\n              [createVNode(1, 'div', 'popover-content', query.query, 16, null, null, null), createVNode(1, 'div', 'arrow', null, 1, null, null, null)],\n              4,\n              null,\n              null,\n              null\n            )\n          ],\n          4,\n          null,\n          null,\n          null\n        )\n      );\n    }\n    databases.push(createVNode(1, 'tr', null, children, 4, null, null, null));\n  }\n\n  render(createVNode(1, 'table', 'table table-striped', createVNode(1, 'tbody', null, databases, 4, null, null, null), 2, null, null, null), elem);\n}\n\nfunction loop() {\n  var dbs = ENV.generateData(false).toArray();\n  // startProfile('view update');\n  renderBenchmark(dbs);\n  // endProfile('view update');\n}\n\nsetInterval(loop, 0);\n"
  },
  {
    "path": "docs/dbmonster/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"UTF-8\">\n\t<title>Inferno</title>\n\t<link rel=\"stylesheet\" href=\"style.css\">\n</head>\n<body>\n\t<div id=\"app\"></div>\n    <script src=\"ENV.js\"></script>\n\t<script src=\"dist/bundle.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/dbmonster/style.css",
    "content": "body {color:#333;font-family:\"Helvetica Neue\",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;margin:0;}\nlabel {display:inline-block;font-weight:700;margin-bottom:5px;}\ninput[type=range] {display:block;width:100%;}\ntable {border-collapse:collapse;border-spacing:0;}\n:before,:after {box-sizing: border-box;}\n\n.table > thead > tr > th,.table > tbody > tr > th,.table > tfoot > tr > th,.table > thead > tr > td,.table > tbody > tr > td,.table > tfoot > tr > td {border-top:1px solid #ddd;line-height:1.42857143;padding:8px;vertical-align:top;}\n.table {width:100%;}\n.table-striped > tbody > tr:nth-child(odd) > td,.table-striped > tbody > tr:nth-child(odd) > th {background:#f9f9f9;}\n\n.label {border-radius:.25em;color:#fff;display:inline;font-size:75%;font-weight:700;line-height:1;padding:.2em .6em .3em;text-align:center;vertical-align:baseline;white-space:nowrap;}\n.label-success {background-color:#5cb85c;}\n.label-warning {background-color:#f0ad4e;}\n\n.popover {background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 5px 10px rgba(0,0,0,.2);display:none;left:0;max-width:276px;padding:1px;position:absolute;text-align:left;top:0;white-space:normal;z-index:1010;}\n.popover>.arrow:after {border-width:10px;content:\"\";}\n.popover.left {margin-left:-10px;}\n.popover.left > .arrow {border-right-width:0;border-left-color:rgba(0,0,0,.25);margin-top:-11px;right:-11px;top:50%;}\n.popover.left > .arrow:after {border-left-color:#fff;border-right-width:0;bottom:-10px;content:\" \";right:1px;}\n.popover > .arrow {border-width:11px;}\n.popover > .arrow,.popover>.arrow:after {border-color:transparent;border-style:solid;display:block;height:0;position:absolute;width:0;}\n\n.popover-content {padding:9px 14px;}\n\n.Query {position:relative;}\n.Query:hover .popover {display:block;left:-100%;width:100%;}"
  },
  {
    "path": "docs/dbmonster-mobx/app.js",
    "content": "// import { startFPSMonitor, startMemMonitor, initProfiler, startProfile, endProfile } from 'perf-monitor';\nimport { createVNode, createComponentVNode, createFragment, render, Component } from 'inferno';\nimport { observerWrap, observerPatch, observer } from 'inferno-mobx';\nimport { action, observable } from 'mobx';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nlet counter = 0;\nconst data = (() => {\n  const generate = () => {\n    const nbQueries = Math.floor(Math.random() * 10 + 1);\n    const queries = [];\n    for (let l = 0; l < 12; l++) {\n      queries.push(\n        updateQuery({\n          query: '***',\n          formatElapsed: '',\n          elapsedClassName: '',\n          elapsed: null,\n          waiting: null\n        })\n      );\n    }\n    return {\n      nbQueries,\n      countClassName: countClassName(nbQueries),\n      queries: queries\n    };\n  };\n  const temp = [];\n  for (let i = 1; i <= 50; i++) {\n    temp.push({\n      dbname: 'cluster' + i,\n      lastSample: generate()\n    });\n    temp.push({\n      dbname: 'cluster' + i + ' replica',\n      lastSample: generate()\n    });\n  }\n  for (const row of temp) {\n    counter = counter + 1;\n    generateRow(row, counter, 12);\n  }\n  return observable(temp);\n})();\n\nfunction formatElapsed(value) {\n  var comps;\n\n  if (value > 60) {\n    comps = (value % 60).toFixed(2).split('.');\n\n    return Math.floor(value / 60) + ':' + comps[0].lpad('0', 2) + '.' + comps[1];\n  }\n\n  return parseFloat(value).toFixed(2);\n}\n\nfunction getElapsedClassName(elapsed) {\n  var className = 'Query elapsed';\n  if (elapsed >= 10.0) {\n    className += ' warn_long';\n  } else if (elapsed >= 1.0) {\n    className += ' warn';\n  } else {\n    className += ' short';\n  }\n  return className;\n}\n\nfunction countClassName(queries) {\n  var countClassName = 'label';\n  if (queries >= 20) {\n    countClassName += ' label-important';\n  } else if (queries >= 10) {\n    countClassName += ' label-warning';\n  } else {\n    countClassName += ' label-success';\n  }\n  return countClassName;\n}\n\nfunction updateQuery(object) {\n  const elapsed = Math.random() * 15;\n  object.elapsed = elapsed;\n  object.formatElapsed = formatElapsed(elapsed);\n  object.elapsedClassName = getElapsedClassName(elapsed);\n  object.query = 'SELECT blah FROM something';\n  object.waiting = Math.random() < 0.5;\n  if (Math.random() < 0.2) {\n    object.query = '<IDLE> in transaction';\n  }\n  if (Math.random() < 0.1) {\n    object.query = 'vacuum';\n  }\n  return object;\n}\n\nfunction cleanQuery(value) {\n  value.formatElapsed = '';\n  value.elapsedClassName = '';\n  value.query = '';\n  value.elapsed = null;\n  value.waiting = null;\n}\n\nfunction generateRow(object, counter, nbQueries) {\n  object.lastMutationId = counter;\n  for (let j = 0; j < 12; j++) {\n    const value = object.lastSample.queries[j];\n    if (j <= nbQueries) {\n      updateQuery(value);\n    } else {\n      cleanQuery(value);\n    }\n  }\n  object.lastSample.nbQueries = nbQueries;\n  object.lastSample.countClassName = countClassName(nbQueries);\n  return object;\n}\n\nfunction updateData() {\n  for (let row of data) {\n    if (Math.random() < mutations()) {\n      counter = counter + 1;\n      generateRow(row, counter, Math.floor(Math.random() * 10 + 1));\n    }\n  }\n}\n\nvar mutationsValue = 0.5;\n\nfunction mutations(value) {\n  if (value) {\n    mutationsValue = value;\n    return mutationsValue;\n  } else {\n    return mutationsValue;\n  }\n}\n\nconst app = document.getElementById('app');\n\nvar body = document.querySelector('body');\nvar theFirstChild = body.firstChild;\n\nvar sliderContainer = document.createElement('div');\nsliderContainer.style.cssText = 'display: flex';\nvar slider = document.createElement('input');\nvar text = document.createElement('label');\ntext.innerHTML = 'mutations : ' + (mutationsValue * 100).toFixed(0) + '%';\ntext.id = 'ratioval';\nslider.setAttribute('type', 'range');\nslider.style.cssText = 'margin-bottom: 10px; margin-top: 5px';\nslider.addEventListener('change', function (e) {\n  mutations(e.target.value / 100);\n  document.querySelector('#ratioval').innerHTML = 'mutations : ' + (mutations() * 100).toFixed(0) + '%';\n});\nsliderContainer.appendChild(text);\nsliderContainer.appendChild(slider);\nbody.insertBefore(sliderContainer, theFirstChild);\n\nclass QueryObserver extends Component {\n  render({ query }) {\n    return createVNode(\n      1,\n      'td',\n      query.elapsedClassName,\n      [\n        createVNode(1, 'div', null, query.formatElapsed, 16, null, null, null),\n        createVNode(\n          1,\n          'div',\n          'popover left',\n          [createVNode(1, 'div', 'popover-content', query.query, 16, null, null, null), createVNode(1, 'div', 'arrow', null, 1, null, null, null)],\n          4,\n          null,\n          null,\n          null\n        )\n      ],\n      4,\n      null,\n      null,\n      null\n    );\n  }\n}\n\nobserver(QueryObserver);\n\nclass QueriesObserver extends Component {\n  render({ top }) {\n    return createFragment(\n      top.slice(0, 5).map((query) => {\n        return createComponentVNode(VNodeFlags.ComponentClass, QueryObserver, { query });\n      }),\n      4\n    );\n  }\n}\n\nobserver(QueriesObserver);\n\nclass RowObserver extends Component {\n  render({ db }) {\n    const lastSample = db.lastSample;\n    const children = [\n      createVNode(1, 'td', 'dbname', db.dbname, 16, null, null, null),\n      createVNode(1, 'td', 'query-count', createVNode(1, 'span', lastSample.countClassName, lastSample.nbQueries, 16, null, null, null), 2, null, null, null),\n      createComponentVNode(VNodeFlags.ComponentClass, QueriesObserver, { top: lastSample.queries })\n    ];\n    return createVNode(1, 'tr', null, children, 4, null, null, null);\n  }\n}\n\nobserver(RowObserver);\n\nclass TableObserver extends Component {\n  render({ list }) {\n    const children = [];\n    for (const db of list) {\n      children.push(createComponentVNode(VNodeFlags.ComponentClass, RowObserver, { db }));\n    }\n    return createVNode(\n      1,\n      'table',\n      'table table-striped',\n      [createVNode(1, 'caption', null, 'inferno-mobx observer', 16, null, null, null), createVNode(1, 'tbody', null, children, 4, null, null, null)],\n      4,\n      null,\n      null,\n      null\n    );\n  }\n}\n\nobserver(TableObserver);\n\nclass QueryClass extends Component {\n  render({ query }) {\n    return createVNode(\n      1,\n      'td',\n      query.elapsedClassName,\n      [\n        createVNode(1, 'div', null, query.formatElapsed, 16, null, null, null),\n        createVNode(\n          1,\n          'div',\n          'popover left',\n          [createVNode(1, 'div', 'popover-content', query.query, 16, null, null, null), createVNode(1, 'div', 'arrow', null, 1, null, null, null)],\n          4,\n          null,\n          null,\n          null\n        )\n      ],\n      4,\n      null,\n      null,\n      null\n    );\n  }\n  shouldComponentUpdate({ query }) {\n    return query !== this.props.query;\n  }\n}\n\nobserverPatch(QueryClass);\n\nclass QueriesClass extends Component {\n  render({ top }) {\n    return createFragment(\n      top.slice(0, 5).map((query) => {\n        return createComponentVNode(VNodeFlags.ComponentClass, QueryClass, { query });\n      }),\n      4\n    );\n  }\n  shouldComponentUpdate({ top }) {\n    return top !== this.props.top;\n  }\n}\n\nobserverPatch(QueriesClass);\n\nclass RowClass extends Component {\n  render({ db }) {\n    const lastSample = db.lastSample;\n    const children = [\n      createVNode(1, 'td', 'dbname', db.dbname, 16, null, null, null),\n      createVNode(1, 'td', 'query-count', createVNode(1, 'span', lastSample.countClassName, lastSample.nbQueries, 16, null, null, null), 2, null, null, null),\n      createComponentVNode(VNodeFlags.ComponentClass, QueriesClass, { top: lastSample.queries })\n    ];\n    return createVNode(1, 'tr', null, children, 4, null, null, null);\n  }\n  shouldComponentUpdate({ db }) {\n    return db !== this.props.db;\n  }\n}\n\nobserverPatch(RowClass);\n\nclass TableClass extends Component {\n  render({ list }) {\n    const children = [];\n    for (const db of list) {\n      children.push(createComponentVNode(VNodeFlags.ComponentClass, RowClass, { db }));\n    }\n    return createVNode(\n      1,\n      'table',\n      'table table-striped',\n      [createVNode(1, 'caption', null, 'inferno-mobx observerPatch', 16, null, null, null), createVNode(1, 'tbody', null, children, 4, null, null, null)],\n      4,\n      null,\n      null,\n      null\n    );\n  }\n  shouldComponentUpdate({ list }) {\n    return list !== this.props.list;\n  }\n}\n\nobserverPatch(TableClass);\n\nfunction QueryComponent({ query }) {\n  return createVNode(\n    1,\n    'td',\n    query.elapsedClassName,\n    [\n      createVNode(1, 'div', null, query.formatElapsed, 16, null, null, null),\n      createVNode(\n        1,\n        'div',\n        'popover left',\n        [createVNode(1, 'div', 'popover-content', query.query, 16, null, null, null), createVNode(1, 'div', 'arrow', null, 1, null, null, null)],\n        4,\n        null,\n        null,\n        null\n      )\n    ],\n    4,\n    null,\n    null,\n    null\n  );\n}\n\nQueryComponent.defaultHooks = {\n  onComponentShouldUpdate: ({ query: prev }, { query: next }) => prev !== next\n};\n\nconst Query = observerWrap(QueryComponent);\n\nfunction QueriesComponent({ top }) {\n  return createFragment(\n    top.slice(0, 5).map((query) => {\n      return createComponentVNode(VNodeFlags.ComponentFunction, Query, { query });\n    }),\n    4\n  );\n}\n\nQueriesComponent.defaultHooks = {\n  onComponentShouldUpdate: ({ top: prev }, { top: next }) => prev !== next\n};\n\nconst Queries = observerWrap(QueriesComponent);\n\nfunction RowComponent({ db }) {\n  const lastSample = db.lastSample;\n  const children = [\n    createVNode(1, 'td', 'dbname', db.dbname, 16, null, null, null),\n    createVNode(1, 'td', 'query-count', createVNode(1, 'span', lastSample.countClassName, lastSample.nbQueries, 16, null, null, null), 2, null, null, null),\n    createComponentVNode(VNodeFlags.ComponentFunction, Queries, { top: lastSample.queries })\n  ];\n  return createVNode(1, 'tr', null, children, 4, null, null, null);\n}\n\nRowComponent.defaultHooks = {\n  onComponentShouldUpdate: ({ db: prev }, { db: next }) => prev !== next\n};\n\nconst Row = observerWrap(RowComponent);\n\nfunction TableComponent({ list }) {\n  const children = [];\n  for (const db of list) {\n    children.push(createComponentVNode(VNodeFlags.ComponentFunction, Row, { db }));\n  }\n  return createVNode(\n    1,\n    'table',\n    'table table-striped',\n    [createVNode(1, 'caption', null, 'inferno-mobx observerWrap', 16, null, null, null), createVNode(1, 'tbody', null, children, 4, null, null, null)],\n    4,\n    null,\n    null,\n    null\n  );\n}\n\nTableComponent.defaultHooks = {\n  onComponentShouldUpdate: ({ list: prev }, { list: next }) => prev !== next\n};\n\nconst Table = observerWrap(TableComponent);\n\nconst update = action(() => {\n  updateData();\n  // startProfile('view update');\n});\n\nfunction loop() {\n  update();\n  // endProfile('view update');\n}\n\n// startFPSMonitor();\n// startMemMonitor();\n// initProfiler('view update');\n\n// functional components with observerWrap\nrender(createComponentVNode(VNodeFlags.ComponentFunction, Table, { list: data }), app);\n\n// class components with observerPatch\n//render(createComponentVNode(VNodeFlags.ComponentClass, TableClass, { list: data }), app);\n\n// class components with observer\n//render(createComponentVNode(VNodeFlags.ComponentClass, TableObserver, { list: data }), app);\n\nsetInterval(loop, 0);\n"
  },
  {
    "path": "docs/dbmonster-mobx/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n\t<meta charset=\"UTF-8\">\n\t<title>Inferno</title>\n\t<link rel=\"stylesheet\" href=\"style.css\">\n</head>\n\n<body>\n\t<div id=\"app\"></div>\n\t<script src=\"dist/bundle.js\"></script>\n</body>\n\n</html>\n"
  },
  {
    "path": "docs/dbmonster-mobx/style.css",
    "content": "body {color:#333;font-family:\"Helvetica Neue\",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;margin:0;}\nlabel {display:inline-block;font-weight:700;margin-bottom:5px;}\ninput[type=range] {display:block;width:100%;}\ntable {border-collapse:collapse;border-spacing:0;}\n:before,:after {box-sizing: border-box;}\n\n.table > caption,.table > thead > tr > th,.table > tbody > tr > th,.table > tfoot > tr > th,.table > thead > tr > td,.table > tbody > tr > td,.table > tfoot > tr > td {border-top:1px solid #ddd;line-height:1.42857143;padding:8px;vertical-align:top;}\n.table {width:100%;}\n.table-striped > tbody > tr:nth-child(odd) > td,.table-striped > tbody > tr:nth-child(odd) > th {background:#f9f9f9;}\n.table > caption {font-weight: 700;}\n\n.label {border-radius:.25em;color:#fff;display:inline;font-size:75%;font-weight:700;line-height:1;padding:.2em .6em .3em;text-align:center;vertical-align:baseline;white-space:nowrap;}\n.label-success {background-color:#5cb85c;}\n.label-warning {background-color:#f0ad4e;}\n\n.popover {background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 5px 10px rgba(0,0,0,.2);display:none;left:0;max-width:276px;padding:1px;position:absolute;text-align:left;top:0;white-space:normal;z-index:1010;}\n.popover>.arrow:after {border-width:10px;content:\"\";}\n.popover.left {margin-left:-10px;}\n.popover.left > .arrow {border-right-width:0;border-left-color:rgba(0,0,0,.25);margin-top:-11px;right:-11px;top:50%;}\n.popover.left > .arrow:after {border-left-color:#fff;border-right-width:0;bottom:-10px;content:\" \";right:1px;}\n.popover > .arrow {border-width:11px;}\n.popover > .arrow,.popover>.arrow:after {border-color:transparent;border-style:solid;display:block;height:0;position:absolute;width:0;}\n\n.popover-content {padding:9px 14px;}\n\n.Query {position:relative;}\n.Query:hover .popover {display:block;left:-100%;width:100%;}\n"
  },
  {
    "path": "docs/event-test/app.js",
    "content": "import { createComponentVNode, linkEvent, render } from 'inferno';\n\nfunction hoistedEvent(e) {\n  console.log('ok', e);\n}\n\nfunction hoistedNonSyntheticEvents() {\n  const listItems = [];\n\n  for (let i = 0; i < numberOfNodes; i++) {\n    listItems.push(\n      <li onclick={hoistedEvent} $HasTextChildren>\n        {i}\n      </li>\n    );\n  }\n\n  return <ul $HasNonKeyedChildren>{listItems}</ul>;\n}\n\nfunction hoistedLinkEventNonSynthetic() {\n  const listItems = [];\n\n  for (let i = 0; i < numberOfNodes; i++) {\n    listItems.push(\n      <li onclick={linkEvent(i, hoistedEvent)} $HasTextChildren>\n        {i}\n      </li>\n    );\n  }\n\n  return <ul $HasNonKeyedChildren>{listItems}</ul>;\n}\n\nfunction hoistedSyntheticEvents() {\n  const listItems = [];\n\n  for (let i = 0; i < numberOfNodes; i++) {\n    listItems.push(\n      <li onClick={hoistedEvent} $HasTextChildren>\n        {i}\n      </li>\n    );\n  }\n\n  return <ul $HasNonKeyedChildren>{listItems}</ul>;\n}\n\nfunction newFuncsNonSyntheticEvents() {\n  const listItems = [];\n\n  for (let i = 0; i < numberOfNodes; i++) {\n    listItems.push(\n      <li\n        onclick={() => {\n          console.log('ok');\n        }}\n        $HasTextChildren\n      >\n        {i}\n      </li>\n    );\n  }\n\n  return <ul $HasNonKeyedChildren>{listItems}</ul>;\n}\n\nconst numberOfNodes = 500;\nconst waitMs = 30;\nconst patchCounter = 7;\nconst iterations = 10;\nconst warmUpIterations = 3;\n\nconst roots = [hoistedNonSyntheticEvents, hoistedLinkEventNonSynthetic, hoistedSyntheticEvents, newFuncsNonSyntheticEvents];\nconst names = ['hoistedNonSyntheticEvents', 'hoistedLinkEventNonSynthetic', 'hoistedSyntheticEvents', 'newFuncsNonSyntheticEvents'];\n\nconst getAvg = (arr) => arr.reduce((a, b) => a + b, 0) / arr.length;\nconst getMin = (arr) => Math.min(...arr);\nconst getMax = (arr) => Math.max(...arr);\n\nfunction Results({ results }) {\n  const rows = [];\n\n  for (let i = 0; i < results.length; i++) {\n    const testData = results[i];\n    const testCases = ['mount', 'patch', 'unmount'];\n\n    rows.push(<div className=\"test-name\">{testData.name}</div>);\n\n    for (let j = 0; j < testCases.length; j++) {\n      const testCase = testCases[j];\n      const result = testData[testCase];\n\n      rows.push(<div className=\"test-part\">{testCase}</div>);\n      rows.push(<div className=\"test-result\">Avg: {result.avg}</div>);\n      rows.push(<div className=\"test-result\">Min: {result.min}</div>);\n      rows.push(<div className=\"test-result\">Max: {result.max}</div>);\n    }\n  }\n\n  return (\n    <div className=\"results\" $HasNonKeyedChildren>\n      {rows}\n    </div>\n  );\n}\n\ndocument.addEventListener('DOMContentLoaded', function (e) {\n  const container = document.querySelector('#App');\n  const result = [];\n  let mountTimes = [];\n  let patchTimes = [];\n  let unmountTimes = [];\n\n  let i = 0;\n\n  for (let q = 0; q < warmUpIterations; q++) {\n    for (let qw = 0; qw < roots.length; qw++) {\n      render(createComponentVNode(1 << 3, roots[qw]), container);\n    }\n  }\n\n  render(null, container);\n\n  function mountTest(finishCallback) {\n    const start = performance.now();\n    // Mount\n    render(createComponentVNode(1 << 3, roots[i]), container);\n\n    const end = performance.now();\n\n    mountTimes.push(end - start);\n\n    setTimeout(patchTest, waitMs, finishCallback);\n  }\n\n  function patchTest(finishCallback) {\n    const start = performance.now();\n\n    // Patch loop\n    for (let p = 0; p < patchCounter; p++) {\n      render(createComponentVNode(1 << 3, roots[i]), container);\n    }\n\n    const end = performance.now();\n\n    patchTimes.push(end - start);\n\n    setTimeout(unmountTest, waitMs, finishCallback);\n  }\n\n  function unmountTest(finishCallback) {\n    const start = performance.now();\n    // Mount\n    render(null, container);\n\n    const end = performance.now();\n\n    unmountTimes.push(end - start);\n\n    setTimeout(finishCallback, waitMs);\n  }\n\n  let iterationCounter = 0;\n\n  function startRound() {\n    if (iterationCounter < iterations && i < roots.length) {\n      iterationCounter++;\n      setTimeout(mountTest, waitMs, startRound);\n    } else if (i < roots.length) {\n      result.push({\n        name: names[i],\n        mount: {\n          min: getMin(mountTimes),\n          avg: getAvg(mountTimes),\n          max: getMax(mountTimes)\n        },\n        patch: {\n          min: getMin(patchTimes),\n          avg: getAvg(patchTimes),\n          max: getMax(patchTimes)\n        },\n        unmount: {\n          min: getMin(unmountTimes),\n          avg: getAvg(unmountTimes),\n          max: getMax(unmountTimes)\n        }\n      });\n\n      mountTimes = [];\n      patchTimes = [];\n      unmountTimes = [];\n\n      i++;\n      iterationCounter = 0;\n\n      startRound(); // Go next\n    } else {\n      // Finished!\n      setTimeout(function () {\n        render(<Results results={result} />, container);\n      }, 1000);\n    }\n  }\n\n  startRound();\n});\n"
  },
  {
    "path": "docs/event-test/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <link href=\"styles.css\" rel=\"stylesheet\" />\n    <title>Event test</title>\n</head>\n<body>\n<div id=\"App\"></div>\n<script src=\"dist/bundle.js\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/event-test/styles.css",
    "content": ".test-result {\n    margin: 5px 0 5px 19px;\n}\n\n.test-name {\n    font-weight: 600;\n}\n\n.results {\n    padding: 20px;\n}\n\n.test-part {\n    font-weight: 600;\n}\n\nul {\n    list-style: none;\n}\n\nbody {\n    margin: 0;\n    padding: 0;\n}\n"
  },
  {
    "path": "docs/form/app.js",
    "content": "import { render, linkEvent } from 'inferno';\nimport { h } from 'inferno-hyperscript';\n\nlet firstName = 'Dominic';\nlet lastName = null;\nlet age = 28;\nlet description = null;\n\n// special input values\nlet id = 'test';\nlet testValue = 11;\nfunction changeTestValue(event) {\n  testValue = event.target.value;\n\n  console.log(event.type, testValue);\n\n  renderForm();\n}\n\nfunction linkedTextHandler(data, e) {\n  const val = e.target.value;\n\n  firstName = val;\n  renderForm();\n}\n\nfunction textHandler(e) {\n  const val = e.target.value;\n\n  lastName = val;\n  renderForm();\n}\n\nfunction numberHandler(e) {\n  const val = e.target.value;\n\n  age = val;\n  renderForm();\n}\n\nfunction descHandler(e) {\n  const val = e.target.value;\n\n  description = val;\n  renderForm();\n}\n\nfunction handleToggle(e) {\n  console.log('Checkbox clicked!');\n}\n\nfunction renderForm() {\n  render(\n    h('form.form', [\n      h('div.form-group', [\n        h('label', 'Please enter your first name name:'),\n        h('input', {\n          type: 'text',\n          placeholder: 'Joe',\n          value: firstName,\n          onInput: linkEvent({ data: '123' }, linkedTextHandler)\n        })\n      ]),\n      h('div.form-group', [\n        h('label', 'Please enter your first last name:'),\n        h('input', {\n          type: 'text',\n          placeholder: 'Bloggs',\n          defaultValue: 'Gannaway',\n          onInput: textHandler\n        })\n      ]),\n      h('div.form-group', [h('label', 'Please enter your age:'), h('input', { type: 'number', value: age, min: 0, max: 99, onInput: numberHandler })]),\n      h('div.form-group', [\n        h('label', 'What is your favourite food:'),\n        h('div.inline', [h('input', { type: 'radio', name: 'food', defaultChecked: false, onClick: handleToggle }), h('span', 'Pizza')]),\n        h('div.inline', [h('input', { type: 'radio', name: 'food', defaultChecked: true, onClick: handleToggle }), h('span', 'Pasta')])\n      ]),\n      h('div.form-group', [\n        h('label', 'Please enter your location:'),\n        h('select', { value: 'United Kingdom' }, [\n          h('option', { selected: false }, 'United States'),\n          h('option', { selected: true }, 'United Kingdom'),\n          h('option', { selected: false }, 'France')\n        ])\n      ]),\n      h('div.form-group', [\n        h('label', 'Please enter a description:'),\n        h('textarea', {\n          defaultValue: \"I don't know?\",\n          value: description,\n          onInput: descHandler\n        })\n      ]),\n      h('div.form-group', [h('label', 'Color picker (html5):'), h('input', { type: 'color' })]),\n      h('label', { for: 'test' }, [\n        'Label',\n        h('input#test', {\n          id: id,\n          name: id,\n          value: testValue,\n          onChange: changeTestValue,\n          onInput: changeTestValue,\n          onKeyup: changeTestValue,\n          type: 'number',\n          pattern: '[0-9]+([,.][0-9]+)?',\n          inputMode: 'numeric',\n          min: 10\n        })\n      ])\n    ]),\n    document.getElementById('app')\n  );\n}\nrenderForm();\n"
  },
  {
    "path": "docs/form/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<title>Inferno Form example</title>\n\t<style>\n\t\tbody {\n\t\t\tmargin: 0;\n\t\t\tpadding: 0;\n\t\t}\n\t\t.form {\n\t\t\tmin-width: 400px;\n\t\t\tmargin: 20px;\n\t\t\toverflow: hidden;\n\t\t\tborder: 1px solid #999;\n\t\t\tbackground: #eee;\n\t\t\tpadding: 20px;\n\t\t\tfont-family: Arial;\n\t\t}\n\t\t.form-group {\n\t\t\tdisplay: block;\n\t\t\toverflow: hidden;\n\t\t\tposition: relative;\n\t\t\tmargin-bottom: 20px;\n\t\t}\n\t\t.form-group label {\n\t\t\tdisplay: block;\n\t\t\tfont-size: 16px;\n\t\t\tcolor: #444;\n\t\t\tmargin-bottom: 5px;\n\t\t}\n\t\t.form-group input {\n\t\t\tdisplay: block;\n\t\t\tmargin-top: 5px;\n\t\t\tfont-size: 14px;\n\t\t\tpadding: 5px;\n\t\t}\n\t\t.form-group .inline input {\n\t\t\tdisplay: inline-block;\n\t\t\tmargin-right: 10px;\n\t\t}\n\t</style>\n</head>\n<body>\n\t<div id=\"app\"></div>\n\t<script src=\"dist/bundle.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Inferno Examples</title>\n    <link rel=\"stylesheet\" href=\"styles.css\"/>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n</head>\n<body>\n    <div class=\"bench-list\">\n        <svg class=\"inferno-logo\" viewBox=\"0 0 320 320\" width=\"80\" height=\"80\" preserveAspectRatio=\"xMidYMid meet\"><g fill=\"#494949\" stroke=\"none\"><path fill=\"#FF3232\" d=\"m144.9 258.5c-43.4-6.1-78.3-46.3-79.2-90-0.7-25.3 8.3-51.7 27-69.1-2 10-8.4 22.4-6.5 34.1 0 14.4 13.7 28.5 28.5 24.6 13.3-3.2 18.3-18.8 14.7-30.8-3.6-16.3-12.1-31.8-9.6-49 2.4-32.4 26.9-58 53.9-73.3 5.5-4 3.6-0.7 1.1 3.2-9.2 14.9-10.5 34-2.6 49.7 11.5 27 34 50.4 35.3 81 0.3 6.3-1.9 22.4 7.3 12 14.6-13.6 13.5-36.2 6.9-53.5-1.8-9.7 9.9 6.6 12.8 9.4 25.3 31.7 26.7 79.9 2.7 112.8-20.1 29.2-57.2 44.9-92.1 38.9z\"></path><path d=\"M139.3 315.4C82.4 307.7 34.8 268.1 16.4 213.1 10.7 196 9.1 185.5 9 165.5c0-12.5 0.4-19.6 1.8-27 11-59.3 54.6-106 112.4-120.6 6.3-1.6 12-2.9 12.8-2.9 2.5 0 1.5 2.1-3.5 7.6-10.7 11.7-19.3 27.7-22.8 42.3l-1.7 7.4-7 4.8C77.3 93 61.3 117.3 56 145.1c-1.9 9.8-2.1 29-0.5 38.1 7.9 43.8 41.7 78.1 85 86.3 16.8 3.2 38.6 1.5 54.3-4.1 31.8-11.4 56-36.3 66-67.9 3.7-11.8 4.8-19.2 4.8-32.3 0-24.5-7-45.2-21.8-64.9-12.9-17.1-28.6-27.9-54.5-37.5-3.3-1.2-7.3-9.7-9.4-19.8-1.6-7.8-0.9-15.2 2.1-22.7 1.5-3.7 2.1-4.2 4.8-4.2 4.9 0 20.8 4.6 31.5 9 45.6 19 79.3 59.9 89.9 109 3.3 15.1 3.7 43.1 0.9 58-14.9 80.2-89.5 134.4-169.9 123.5z\" fill=\"#494949\"></path></g></svg>\n        <h1>Inferno Examples and Benchmarks</h1>\n\n        <h2>Benchmarks</h2>\n        <p>\n          <a href=\"1kcomponents/index.html\">1k Components</a><br />\n          This benchmark measures creation time of multiple functional components.<br />\n          Rendering speed is heavily bottlenecked by patchStyle method.<br />\n          <small><a href=\"1kcomponents/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/1kcomponents/app.js\">View source...</a></small>\n        </p>\n        <p>\n          <a href=\"dbmonster/index.html\">DBMonster</a><br />\n          This benchmark measures time of patching same number of elements.<br />\n          <small><a href=\"dbmonster/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/dbmonster/app.js\">View source...</a></small>\n        </p>\n        <p>\n          <a href=\"uibench/index.html\">UI Benchmark</a><br />\n          InfernoJS implementation of UI Benchmark. This benchmark uses optimization patterns specific to InfernoJS only.<br />\n          <small><a href=\"uibench/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/uibench/app.js\">View source...</a></small>\n        </p>\n        <p>\n            <a href=\"uibench-inferno-compat/index.html\">UI Benchmark (Inferno-compat)</a><br />\n            Same as regular ui benchmark implementation, but uses inferno-compat to track performance regressions in compatibility layer.<br />\n            <small><a href=\"uibench-inferno-compat/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/uibench-inferno-compat/app.js\">View source...</a></small>\n        </p>\n        <p>\n            <a href=\"uibench-normalization/index.html\">UI Benchmark (Normalization)</a><br />\n            This version of UI Benchmark tracks performance regressions in Inferno's normalization algorithm. Do not write code like this.<br />\n            <small><a href=\"uibench-normalization/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/uibench-normalization/app.js\">View source...</a></small>\n        </p>\n        <p>\n          <a href=\"uibench-lifecycle/index.html\">UI Benchmark (Lifecycle)</a><br />\n          This version of UI Benchmark tracks performance regressions in Inferno's lifecycle process. Do not write code like this.<br />\n          <small><a href=\"uibench-lifecycle/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/uibench-lifecycle/app.js\">View source...</a></small>\n        </p>\n        <p>\n            <a href=\"uibench-reactlike/index.html\">UI Benchmark (same as React)</a><br />\n            This is InfernoJS implementation of UI Benchmark using identical application level code with React implementation.<br />\n            <small><a href=\"uibench-reactlike/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/uibench-reactlike/app.js\">View source...</a></small>\n        </p>\n\n        <h2>Examples</h2>\n        <p>\n          <a href=\"animations-demo/index.html\">Animations demo</a><br />\n          This demo uses inferno-animation to animate multiple elements of a card when it is added and removed from the DOM.<br />\n          <small><a href=\"animations-demo/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/animations-demo/app.js\">View source...</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/animations-demo/app.css\">View CSS...</a></small>\n        </p>\n        <p>\n          <a href=\"animations-demo-inner/index.html\">Animating child when parent is mounted/unmounted</a><br />\n          Here the animation is only performed on a child component of page when the page is mounted and unnmounted.<br />\n          <small><a href=\"animations-demo-inner/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/animations-demo-inner/app.js\">View source...</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/animations-demo-inner/app.css\">View CSS...</a></small>\n        </p>\n        <p>\n          <a href=\"animations/index.html\">Animations on mount and unmount</a><br />\n          This is an implementation of inferno-animation where components are animated when added, removed or moved in the DOM.<br />\n          <small><a href=\"animations/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/animations/app.js\">View source...</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/animations/app.css\">View CSS...</a></small>\n        </p>\n        <p>\n          <a href=\"animations-global-demo/index.html\">Global animations</a><br />\n          Component exists on two different \"pages\" and when we switch between them it animates between the two positions.<br />\n          <small><a href=\"animations-global-demo/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/animations-global-demo/app.js\">View source...</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/animations-global-demo/app.css\">View CSS...</a></small>\n        </p>\n        <p>\n            <a href=\"async-render/index.html\">Async render</a><br />\n            Render 2 x 2k rows using loop in componentDidMount.<br />\n            <small><a href=\"async-render/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/async-render/app.js\">View source...</a></small>\n        </p>\n        <p>\n          <a href=\"compat/index.html\">React Compatibility</a><br />\n          Using React compatibility extension.<br />\n          <small><a href=\"1kcomponents/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/compat/index.html\">View source...</a></small>\n        </p>\n        <p>\n            <a href=\"form/index.html\">Input Forms</a><br />\n            Inferno and HTML-forms.<br />\n            <small><a href=\"form/index.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/form/index.html\">View source...</a></small>\n        </p>\n        <p>\n            <a href=\"svg/tiger.html\">Inferno and SVG</a><br />\n            The tiger rendered with an SVG in Inferno.<br />\n            <small><a href=\"svg/tiger.html\">Example</a> | <a href=\"https://github.com/infernojs/inferno/blob/master/docs/svg/tiger.html\">View source...</a></small>\n        </p>\n    </div>\n</body>\n</html>\n"
  },
  {
    "path": "docs/math-elements/app.js",
    "content": "import { Component, render } from 'inferno';\n\nclass Demo extends Component {\n  constructor(props, context) {\n    super(props, context);\n\n    this.state = {\n      numPoints: 0\n    };\n\n    this.updateCount = this.updateCount.bind(this);\n  }\n\n  updateCount(e) {\n    this.setState({\n      numPoints: e.target.value\n    });\n  }\n\n  componentDidMount() {\n    this.setState({\n      numPoints: 1000\n    });\n  }\n\n  render(props, state) {\n    return (\n      <div className=\"app-wrapper\">\n        <p>\n          The infinite sum\n          <math display=\"block\">\n            <mrow>\n              <munderover>\n                <mo>∑</mo>\n                <mrow>\n                  <mi>n</mi>\n                  <mo>=</mo>\n                  <mn>1</mn>\n                </mrow>\n                <mrow>\n                  <mo>+</mo>\n                  <mn>∞</mn>\n                </mrow>\n              </munderover>\n              <mfrac>\n                <mn>1</mn>\n                <msup>\n                  <mi>n</mi>\n                  <mn>2</mn>\n                </msup>\n              </mfrac>\n            </mrow>\n          </math>\n          is equal to the real number\n          <math display=\"inline\">\n            <mfrac>\n              <msup>\n                <mi>π</mi>\n                <mn>2</mn>\n              </msup>\n              <mn>6</mn>\n            </mfrac>\n          </math>\n          .\n        </p>\n      </div>\n    );\n  }\n}\n\nrender(<Demo />, document.getElementById('app'));\n"
  },
  {
    "path": "docs/math-elements/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <meta charset=\"utf-8\"/>\n    <link rel=\"stylesheet\" href=\"style.css\">\n</head>\n<body>\n<div id=\"app\"></div>\n<script src=\"dist/bundle.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/math-elements/style.css",
    "content": "html,\nbody {\n    padding: 0;\n    margin: 0;\n    font-family: sans-serif;\n    width: 100%;\n    height: 100%;\n    background: #111;\n    color: #777;\n}\n\na {\n    color: #777;\n}\n\n.demo {\n    overflow-x: hidden;\n    position: relative;\n}\n.point {\n    width: 4px;\n    height: 4px;\n    position: absolute;\n    shape-rendering: optimizeSpeed;\n}\n.controls {\n    position: fixed;\n    top: 0;\n    width: 100%;\n    padding: 15px;\n    background: #e41f1c;\n    border-bottom: 1px solid darkred;\n    display: -webkit-box;\n    display: -ms-flexbox;\n    display: flex;\n    -webkit-box-pack: center;\n    -ms-flex-pack: center;\n    justify-content: center;\n    color: white;\n    white-space: nowrap;\n}\n.controls > input {\n    margin: 0 10px;\n    width: 50%;\n}\n.controls label {\n    margin-left: 30px;\n}\n#stats {\n    position: fixed;\n    top: 0;\n    right: 0;\n}\n.about {\n    position: fixed;\n    bottom: 0;\n    width: 100%;\n    padding: 10px;\n}\n#app,\n.app-wrapper,\n.demo {\n    width: 100%;\n    height: 100%;\n    overflow: hidden;\n}\n"
  },
  {
    "path": "docs/styles.css",
    "content": "html {\n  line-height: 1.42857143;\n}\n\nbody {\n    margin: 0;\n    padding: 0 5vw;\n    font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;\n    font-weight: 400;\n    -webkit-font-smoothing: antialiased;\n    background-color: white;\n    min-height: 100vh;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    justify-content: center;\n    color: #454a57;\n}\n\nh1 {\n  border-bottom: 1px solid #e0e0e0;\n  line-height: 4rem;\n  margin-bottom: 1rem;\n  font-size: 2.2rem;\n  font-weight: 500;\n}\n\nh2 {\n  font-weight: 400;\n  font-size: 1.5rem;\n  color: #000;\n  padding-top: 1rem;\n  margin-bottom: 1rem;\n}\n\na {\n    color: #ff0038;\n    text-decoration: none;\n    opacity: 1;\n    transition: opacity .2s linear;\n    display: inline-block;\n    -webkit-backface-visibility: hidden;\n}\n\np {\n    text-align: left;\n}\n\na:hover {\n    opacity: .5;\n    text-decoration: underline;\n}\n\n.bench-list {\n    max-width: 700px;\n    margin: 5vh 0;\n}\n\n.inferno-logo {\n    background: #fff;\n    width: 6rem;\n    height: 6rem;\n    padding: 2rem;\n    border-radius: 2rem;\n}\n"
  },
  {
    "path": "docs/svg/app.js",
    "content": "import { render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\nvar tiger = createElement(\n  'svg',\n  {\n    version: '1.1',\n    baseProfile: 'basic',\n    id: 'svg2',\n    xmlns: 'http://www.w3.org/2000/svg',\n    x: '0px',\n    y: '0px',\n    width: '900px',\n    height: '900px',\n    viewBox: '0 0 900 900'\n  },\n  createElement('path', { id: 'path482', fill: 'none', d: 'M184.013,144.428' }),\n  createElement('path', {\n    id: 'path6',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M108.956,403.826c0,0,0.178,3.344-1.276,3.311  c-1.455-0.033-30.507-84.917-66.752-80.957C40.928,326.18,72.326,313.197,108.956,403.826z'\n  }),\n  createElement('path', {\n    id: 'path10',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M115.189,398.488c0,0-0.97,3.207-2.327,2.679  c-1.356-0.526,0.203-90.231-35.227-98.837C77.635,302.33,111.576,300.804,115.189,398.488z'\n  }),\n  createElement('path', {\n    id: 'path14',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M163.727,473.225c0,0,2.888,1.695,2.059,2.892  c-0.832,1.194-87.655-21.408-104.35,11.003C61.436,487.118,67.931,453.771,163.727,473.225z'\n  }),\n  createElement('path', {\n    id: 'path18',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M158.767,491.254c0,0,3.277,0.699,2.864,2.096  c-0.411,1.396-89.935,7.298-95.567,43.318C66.063,536.668,61.723,502.971,158.767,491.254z'\n  }),\n  createElement('path', {\n    id: 'path22',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M151.332,481.498c0,0,3.139,1.171,2.528,2.492  c-0.611,1.319-90.037-5.899-100.864,28.915C52.996,512.905,53.617,478.938,151.332,481.498z'\n  }),\n  createElement('path', {\n    id: 'path26',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M132.43,449.356c0,0,2.31,2.427,1.181,3.347  c-1.128,0.919-78.363-44.729-103.341-18.171C30.27,434.532,45.704,404.264,132.43,449.356z'\n  }),\n  createElement('path', {\n    id: 'path30',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M119.108,456.757c0,0,2.571,2.148,1.554,3.192  c-1.017,1.041-82.921-35.576-104.734-6.36C15.928,453.589,27.837,421.769,119.108,456.757z'\n  }),\n  createElement('path', {\n    id: 'path34',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M114.518,463.946c0,0,2.839,1.778,1.974,2.95  c-0.865,1.171-86.997-23.942-104.623,7.974C11.869,474.87,19.329,441.724,114.518,463.946z'\n  }),\n  createElement('path', {\n    id: 'path38',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M133.47,465.03c0,0,1.981,2.703,0.743,3.472  c-1.237,0.768-71.985-54.405-100.161-31.267C34.052,437.235,53.236,409.195,133.47,465.03z'\n  }),\n  createElement('path', {\n    id: 'path42',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M98.546,413.917c0,0,1.06,3.178-0.353,3.531  c-1.413,0.353-51.91-73.804-85.812-60.385C12.381,357.063,39.22,336.229,98.546,413.917z'\n  }),\n  createElement('path', {\n    id: 'path46',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M99.773,426.239c0,0,1.722,2.876,0.417,3.523  c-1.303,0.649-66.605-60.873-96.813-40.458C3.376,389.306,25.088,363.174,99.773,426.239z'\n  }),\n  createElement('path', {\n    id: 'path50',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.172',\n    d: 'M99.57,433.955c0,0,1.981,2.703,0.744,3.472  c-1.238,0.767-71.985-54.405-100.162-31.267C0.152,406.16,19.335,378.12,99.57,433.955z'\n  }),\n  createElement('path', {\n    id: 'path54',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    d: 'M95.668,436.985c0.888,10.678,2.632,22.275,5.703,27.783  c0,0-6.356,21.895,9.181,45.2c0,0-0.707,12.712,2.119,18.362c0,0,7.063,14.832,15.538,16.244c6.858,1.143,22.26,6.561,39.67,9.04  c0,0,30.249,24.859,24.599,47.461c0,0-0.706,28.956-7.063,31.781c0,0,20.481-19.775,3.531,9.888l-7.769,33.192  c0,0,45.201-38.138,17.657-5.648l-17.657,45.906c0,0,34.607-32.487,21.894-17.656l-5.65,15.538c0,0,76.276-48.025,21.894,4.237  c0,0,14.125-6.356,21.894-1.412c0,0,12.006-2.119,10.594,0.706c0,0-36.726,18.361-43.082,50.851c0,0,14.831-17.657,9.181,1.412  l0.706,20.48c0,0,7.063-38.138,6.356,28.25c0,0,33.9-31.78,13.419,4.944v29.662c0,0,26.838-28.956,15.538-6.354  c0,0,17.656-15.538,10.594,11.3c0,0-1.413,18.361,6.356-1.412c0,0,28.25-54.029,17.656-7.771c0,0-1.412,33.9,7.063,7.771  c0,0,0.706,18.362,16.95,31.075c0,0-2.119-89.695,20.48-26.133l7.063,28.957c0,0,4.943-16.244,4.237-25.426  c0,0,26.132-28.957,14.125,14.125c0,0,26.838-40.257,21.188-16.95c0,0-13.419,28.251-10.594,36.727c0,0,29.663-61.444,31.782-64.271  c0,0-3.531,74.865,15.537,11.3c0,0,9.888,21.188,4.943,28.957c0,0,14.125-14.125,12.712-19.774c0,0,8.122-14.479,13.066,9.534  c0,0,3.178,16.598,6.003,10.946c0,0,7.063,42.377,9.182,2.119c0,0,2.825-24.013-9.888-44.494c0,0,1.412-5.649-3.531-12.713  c0,0,24.014,38.139,11.3-12.713c0,0,19.777,14.125,21.896,14.125c0,0-24.015-40.963-8.477-32.487c0,0-9.183-18.362,22.602,2.825  c0,0-28.252-28.251,2.825-11.301c0,0,14.125,11.301,0.706-6.356c0,0-25.428-28.25,13.419,3.532c0,0,20.48,28.956,21.895,33.9  c0,0-17.655-51.559-25.426-56.501c0,0,14.832-64.271,87.576-36.727c0,0,12.007,30.369,19.774-2.118c0,0,22.602-11.301,42.375,37.432  c0,0,7.063-24.013,5.65-28.956c0,0,12.007,2.119,10.594,0c0,0,23.308,7.769,25.427,6.356c0,0,12.006,12.006,12.712,5.648  c0,0,16.244,4.944,12.713-1.412c0,0,15.538,27.544,16.244,33.9l4.236-24.719l3.531,4.942c0,0,2.825-13.419,1.413-15.537  c-1.413-2.119,35.313,12.006,43.787,48.731l3.531,14.831c0,0,10.594-26.131,7.77-33.193c0,0,9.181,1.412,9.888,9.181  c0,0,7.063-40.963-1.412-51.557c0,0,7.769-1.412,9.888,4.944V714.78c0,0,12.713,1.411,12.713-2.825c0,0,7.769-7.063,11.3,1.412  c0,0-21.894-62.15,10.594-28.25c0,0,12.714,19.068,6.356-14.125c-6.357-33.194-13.419-36.021-4.943-36.727  c0,0,1.412-6.355-2.118-9.181c-3.531-2.825,2.118,0,2.118,0s8.476,7.063-0.707-31.782c0,0,11.302,2.825-9.888-48.73  c0,0,4.944-4.237-2.118-19.069c0,0,14.125,7.77,19.069,4.944c0,0-0.707-2.825-6.356-9.889c0,0-38.139-96.759-2.118-57.913  c0,0,20.923,23.925,9.623-16.332c0,0-16.088-42.394-14.716-49.979L95.668,436.985z'\n  }),\n  createElement('path', {\n    id: 'path58',\n    fill: '#CC7226',\n    stroke: '#000000',\n    d: 'M854.095,396.693c1.108,0.32,5.004,2.304,7.211,5.217  c0,0,12.006,19.068,2.825-13.418c0,0-16.244-50.851-0.707-31.076c0,0,10.594,12.713,4.944-11.3  c-6.824-29.004-11.301-40.257-11.301-40.257s20.48,8.475-26.837-61.444l15.536,6.356c0,0-34.605-69.919-72.743-79.101  l-14.125-10.594c0,0,67.8-67.094,45.199-132.07c0,0-12.007-9.182-28.957,7.063c0,0-11.3,8.475-21.894,5.65  c0,0-54.382,2.119-57.913,2.119S630.359-21.844,514.533,9.231c0,0-9.183,3.531-16.95,1.413c0,0-32.489-28.25-118.653,12.006  c0,0-17.655,3.531-20.48,3.531s-7.77,0-21.895,11.3c-14.125,11.3-14.832,12.712-18.362,15.538c0,0-28.957,19.775-37.432,21.188  c0,0-20.481,11.3-28.25,28.957l-6.356,2.119c0,0-2.825,12.713-3.532,14.832c0,0-8.475,6.356-9.887,16.244  c0,0-15.538,10.594-14.832,18.362c0,0-2.825,9.182-4.238,17.657c0,0-12.712,8.475-11.3,13.419c0,0-13.419,24.719-11.3,36.725  c0,0-11.3-0.706-16.244,3.531c0,0-1.413,8.475-4.238,9.182c0,0-4.944,2.119-0.706,9.181c0,0-2.825,4.944-3.531,7.769  c0,0,1.412,4.944-6.356,14.831c0,0-11.3,33.194-7.769,42.375c0,0,0.707,8.475-4.237,11.3c0,0-6.356-0.707,8.475,20.481  c0,0,1.413,2.119-4.238,6.356c0,0-30.369,6.356-34.606,35.313c0,0-24.013,26.131-24.013,35.313c0,4.069,0.479,9.626,1.713,17.771  c0,0-1.007,14.718,47.725,16.131C191.772,453.469,854.095,396.693,854.095,396.693z'\n  }),\n  createElement('path', {\n    id: 'path62',\n    fill: '#CC7226',\n    d: 'M120.793,436.164c-44.141-69.566-18.716,30.018-18.716,30.018  c15.538,60.738,244.365-5.649,244.365-5.649s298.042-53.677,317.816-60.739c19.775-7.063,187.864,4.237,187.864,4.237l-9.888-29.663  c-114.414-81.926-148.314-40.963-172.327-48.025c-24.013-7.062-19.774,9.888-25.425,11.3c-5.651,1.412-74.863-42.375-86.163-40.963  c-11.301,1.413-56.045-40.523-29.663,15.538c28.25,60.032-103.115,69.213-132.778,49.438  c-29.663-19.775,12.713,32.488,12.713,32.488c32.487,35.313-28.25,5.65-28.25,5.65c-60.737-22.601-103.114,22.6-108.764,24.013  c-5.65,1.412-14.125,7.063-15.538-4.237c-1.412-11.301-14.672-40.789-70.625,5.649c-35.313,29.313-59.679-9.534-59.679-9.534  L120.793,436.164z'\n  }),\n  createElement('path', {\n    id: 'path66',\n    fill: '#E87F3A',\n    d: 'M560.632,299.761c-11.3,1.413-56.089-40.502-29.662,15.538  c29.311,62.151-103.113,69.213-132.775,49.438c-29.665-19.775,12.712,32.488,12.712,32.488c32.488,35.313-28.252,5.649-28.252,5.649  c-60.737-22.6-103.113,22.601-108.763,24.013c-5.65,1.413-14.125,7.063-15.538-4.236c-1.413-11.301-14.441-40.494-70.626,5.649  c-37.495,30.627-61.315-7.255-61.315-7.255l-5.65,17.849c-44.141-70.271-17.529,32.682-17.529,32.682  c15.54,60.739,245.521-7.962,245.521-7.962s298.043-53.676,317.817-60.738c19.774-7.062,186.325,4.109,186.325,4.109l-9.762-30.563  c-114.413-81.926-146.9-39.935-170.914-46.998c-24.013-7.063-19.774,9.888-25.425,11.3  C641.146,342.136,571.933,298.349,560.632,299.761z'\n  }),\n  createElement('path', {\n    id: 'path70',\n    fill: '#EA8C4D',\n    d: 'M562.943,302.842c-11.301,1.413-54.973-41.014-29.663,15.538  c28.604,63.918-103.113,69.215-132.776,49.44c-29.662-19.775,12.713,32.488,12.713,32.488c32.488,35.313-28.25,5.649-28.25,5.649  c-60.738-22.6-103.115,22.601-108.766,24.013c-5.65,1.413-14.125,7.063-15.538-4.236c-1.413-11.301-14.21-40.198-70.625,5.649  c-39.68,31.942-62.952-4.976-62.952-4.976l-6.356,15.216c-42.022-68.86-16.341,35.345-16.341,35.345  c15.538,60.738,246.678-10.271,246.678-10.271s298.04-53.677,317.814-60.738c19.775-7.063,184.783,3.979,184.783,3.979l-9.63-31.46  c-114.415-81.926-145.49-38.909-169.503-45.972c-24.014-7.063-19.775,9.888-25.427,11.302  C643.457,345.219,574.243,301.429,562.943,302.842z'\n  }),\n  createElement('path', {\n    id: 'path74',\n    fill: '#EC9961',\n    d: 'M565.255,305.925c-11.301,1.413-54.963-41.02-29.663,15.538  c29.663,66.311-104.057,68.586-132.775,49.438c-29.663-19.775,12.713,32.488,12.713,32.488c32.486,35.313-28.25,5.649-28.25,5.649  c-60.738-22.6-103.114,22.601-108.764,24.013c-5.65,1.413-14.125,7.063-15.538-4.236c-1.413-11.301-13.979-39.9-70.627,5.649  c-41.862,33.259-64.591-2.696-64.591-2.696l-7.063,12.584c-38.491-64.976-15.151,38.012-15.151,38.012  c15.538,60.736,247.833-12.586,247.833-12.586s298.04-53.677,317.817-60.738c19.773-7.063,183.24,3.853,183.24,3.853l-9.502-32.358  c-114.414-81.928-144.076-37.882-168.09-44.945c-24.015-7.063-19.775,9.888-25.427,11.3  C645.766,348.301,576.555,304.512,565.255,305.925z'\n  }),\n  createElement('path', {\n    id: 'path78',\n    fill: '#EEA575',\n    d: 'M567.567,309.008c-11.303,1.412-54.07-41.412-29.664,15.538  c29.664,69.213-103.114,69.213-132.776,49.438c-29.663-19.775,12.713,32.487,12.713,32.487c32.487,35.313-28.251,5.65-28.251,5.65  c-60.738-22.6-103.113,22.601-108.763,24.013c-5.65,1.412-14.125,7.063-15.538-4.237s-13.746-39.604-70.626,5.649  c-44.046,34.575-66.229-0.418-66.229-0.418l-7.769,9.953c-34.96-61.446-13.964,40.673-13.964,40.673  c15.538,60.74,248.989-14.895,248.989-14.895s298.043-53.677,317.816-60.738c19.775-7.063,181.701,3.724,181.701,3.724  l-9.374-33.259c-114.414-81.926-142.664-36.853-166.677-43.915c-24.014-7.062-19.775,9.888-25.426,11.3  C648.081,351.383,578.868,307.595,567.567,309.008z'\n  }),\n  createElement('path', {\n    id: 'path82',\n    fill: '#F1B288',\n    d: 'M569.879,312.089c-11.3,1.412-57.144-39.994-29.663,15.538  c33.9,68.507-103.115,69.213-132.778,49.438c-29.661-19.775,12.714,32.487,12.714,32.487c32.487,35.313-28.25,5.65-28.25,5.65  c-60.738-22.6-103.114,22.601-108.764,24.013c-5.65,1.412-14.125,7.063-15.538-4.237c-1.413-11.3-13.514-39.309-70.626,5.649  c-46.228,35.893-67.866,1.863-67.866,1.863l-8.475,7.317c-31.782-58.619-12.776,43.341-12.776,43.341  C123.394,553.887,358,475.94,358,475.94s298.042-53.677,317.817-60.738c19.774-7.063,180.158,3.595,180.158,3.595l-9.244-34.156  c-114.413-81.926-141.251-35.827-165.265-42.889c-24.013-7.062-19.774,9.888-25.426,11.3  C650.393,354.464,581.179,310.676,569.879,312.089z'\n  }),\n  createElement('path', {\n    id: 'path86',\n    fill: '#F3BF9C',\n    d: 'M572.19,315.169c-11.303,1.413-57.813-39.656-29.665,15.538  c36.021,70.627-103.113,69.214-132.776,49.439s12.713,32.488,12.713,32.488c32.487,35.313-28.25,5.65-28.25,5.65  c-60.738-22.601-103.114,22.6-108.764,24.013c-5.65,1.412-14.125,7.063-15.538-4.237c-1.412-11.301-13.283-39.014-70.625,5.649  c-48.412,37.208-69.503,4.141-69.503,4.141l-9.181,4.688c-28.25-53.322-11.59,46.004-11.59,46.004  c15.538,60.738,251.301-19.519,251.301-19.519s298.041-53.677,317.816-60.738c19.775-7.063,178.619,3.466,178.619,3.466  l-9.117-35.055c-114.414-81.926-139.84-34.799-163.853-41.862c-24.014-7.064-19.774,9.888-25.425,11.3  C652.702,357.546,583.49,313.757,572.19,315.169z'\n  }),\n  createElement('path', {\n    id: 'path90',\n    fill: '#F5CCB0',\n    d: 'M574.501,318.252c-11.3,1.413-59.753-38.624-29.662,15.538  c38.844,69.92-103.115,69.213-132.778,49.438c-29.662-19.775,12.714,32.488,12.714,32.488c32.486,35.313-28.251,5.65-28.251,5.65  c-60.737-22.602-103.113,22.6-108.764,24.013c-5.65,1.412-14.125,7.063-15.538-4.237c-1.413-11.301-13.05-38.716-70.626,5.649  c-50.594,38.524-71.14,6.422-71.14,6.422l-9.887,2.054c-25.427-50.145-10.401,48.668-10.401,48.668  c15.538,60.74,252.455-21.829,252.455-21.829s298.043-53.677,317.816-60.738c19.775-7.063,177.078,3.339,177.078,3.339  l-8.987-35.956c-114.414-81.926-138.428-33.771-162.439-40.834c-24.013-7.063-19.774,9.888-25.425,11.3  C655.015,360.628,585.802,316.84,574.501,318.252z'\n  }),\n  createElement('path', {\n    id: 'path94',\n    fill: '#F8D8C4',\n    d: 'M576.813,321.335c-11.3,1.413-59.753-38.625-29.662,15.538  c38.845,69.919-103.113,69.213-132.776,49.438c-29.662-19.775,12.713,32.488,12.713,32.488c32.488,35.313-28.25,5.65-28.25,5.65  c-60.74-22.602-103.115,22.6-108.766,24.013c-5.65,1.412-14.125,7.063-15.538-4.238c-1.413-11.3-12.817-38.42-70.625,5.65  c-52.777,39.84-72.776,8.701-72.776,8.701l-10.594-0.579c-24.015-46.615-9.213,51.332-9.213,51.332  c15.538,60.738,253.609-24.143,253.609-24.143s298.042-53.675,317.817-60.736c19.775-7.063,175.538,3.21,175.538,3.21l-8.859-36.854  c-114.416-81.926-137.016-32.744-161.027-39.807c-24.013-7.063-19.775,9.888-25.427,11.3  C657.326,363.711,588.112,319.923,576.813,321.335z'\n  }),\n  createElement('path', {\n    id: 'path98',\n    fill: '#FAE5D7',\n    d: 'M579.124,324.417c-11.301,1.413-59.068-38.998-29.663,15.538  c38.844,72.038-103.113,69.213-132.776,49.438c-29.662-19.775,12.714,32.488,12.714,32.488c32.486,35.313-28.251,5.65-28.251,5.65  c-60.737-22.602-103.113,22.6-108.764,24.013c-5.652,1.412-14.127,7.063-15.54-4.238c-1.412-11.3-12.585-38.123-70.625,5.65  c-54.959,41.157-74.413,10.979-74.413,10.979l-11.302-3.212c-22.954-42.375-8.025,53.999-8.025,53.999  c15.538,60.738,254.769-26.455,254.769-26.455s298.04-53.675,317.814-60.736c19.775-7.063,173.997,3.082,173.997,3.082  l-8.732-37.752c-114.413-81.928-135.602-31.718-159.613-38.781c-24.014-7.063-19.774,9.888-25.426,11.3  S590.424,323.004,579.124,324.417z'\n  }),\n  createElement('path', {\n    id: 'path102',\n    fill: '#FCF2EB',\n    d: 'M581.435,327.498c-11.3,1.412-57.161-39.981-29.661,15.538  c37.432,75.571-103.114,69.215-132.776,49.439c-29.663-19.775,12.713,32.488,12.713,32.488c32.487,35.313-28.251,5.649-28.251,5.649  c-60.738-22.601-103.113,22.601-108.763,24.013c-5.65,1.413-14.125,7.063-15.538-4.237c-1.413-11.3-12.354-37.827-70.626,5.65  c-57.145,42.473-76.053,13.258-76.053,13.258l-12.006-5.842c-22.6-40.964-6.836,56.661-6.836,56.661  c15.538,60.736,255.921-28.766,255.921-28.766s298.043-53.676,317.817-60.737c19.775-7.063,172.454,2.951,172.454,2.951  l-8.604-38.65c-114.415-81.926-134.188-30.688-158.2-37.751c-24.014-7.064-19.775,9.887-25.426,11.3  C661.948,369.875,592.735,326.085,581.435,327.498z'\n  }),\n  createElement('path', {\n    id: 'path106',\n    fill: '#FFFFFF',\n    d: 'M120.44,466.182c-22.601-38.846-5.65,59.325-5.65,59.325  c15.538,60.738,257.078-31.075,257.078-31.075s298.042-53.677,317.816-60.738c19.775-7.063,170.914,2.823,170.914,2.823  l-8.475-39.55c-114.414-81.926-132.776-29.663-156.789-36.726c-24.013-7.063-19.775,9.888-25.426,11.3  c-5.649,1.413-74.862-42.375-86.163-40.963c-11.3,1.412-55.829-40.623-29.663,15.538c39.245,84.232-107.28,66.436-132.777,49.438  c-29.663-19.775,12.712,32.488,12.712,32.488c32.488,35.313-28.25,5.65-28.25,5.65c-60.737-22.602-103.113,22.602-108.764,24.014  c-5.65,1.413-14.125,7.063-15.538-4.237c-1.413-11.302-12.121-37.532-70.625,5.65c-59.326,43.788-77.688,15.537-77.688,15.537  L120.44,466.182z'\n  }),\n  createElement('path', {\n    id: 'path110',\n    d: 'M193.891,519.15c0,0-12.713,20.48,24.013,43.788c0,0,2.472,2.473-29.31-4.943c0,0-10.947-3.531-13.771-21.896  c0,0-8.475-7.769-16.95-17.655C149.397,508.557,193.891,519.15,193.891,519.15z'\n  }),\n  createElement('path', {\n    id: 'path114',\n    fill: '#CCCCCC',\n    d: 'M441.08,435.104c0,0,31.249,47.356,30.193,55.797c-2.297,18.362-2.648,35.313,3.001,42.376  c5.651,7.063,21.188,65.682,21.188,65.682s-0.706,2.119,21.188-64.976c0,0,20.48-28.25-14.831-60.738  C501.82,473.244,439.668,422.392,441.08,435.104z'\n  }),\n  createElement('path', {\n    id: 'path118',\n    d: 'M229.204,566.47c0,0,19.775,12.713-5.65,67.802l11.3-4.237c0,0-1.413,19.774-7.063,24.013l12.712-5.65  c0,0,8.475,14.127,1.413,22.602c0,0,29.663,14.125,28.25,25.425c0,0,11.3-14.125,4.237-25.425s-19.775-4.237-18.363-36.727  l-15.538,5.65c0,0,9.888-15.538,9.888-26.838l-14.125,4.237c0,0,27.313-46.928,8.475-49.438  C234.147,566.47,229.204,566.47,229.204,566.47z'\n  }),\n  createElement('path', {\n    id: 'path122',\n    fill: '#CCCCCC',\n    d: 'M286.41,596.133c0,0,4.944-7.769,0-6.355c-4.944,1.413-60.032,27.544-70.625,44.494  C215.785,634.271,276.522,591.189,286.41,596.133z'\n  }),\n  createElement('path', {\n    id: 'path126',\n    fill: '#CCCCCC',\n    d: 'M304.773,610.258c0,0,4.944-7.769,0-6.355s-60.032,27.544-70.625,44.494  C234.147,648.396,294.885,605.314,304.773,610.258z'\n  }),\n  createElement('path', {\n    id: 'path130',\n    fill: '#CCCCCC',\n    d: 'M328.079,583.42c0,0,4.944-7.769,0-6.355c-4.943,1.412-60.032,27.545-70.625,44.494  C257.454,621.559,318.191,578.477,328.079,583.42z'\n  }),\n  createElement('path', {\n    id: 'path134',\n    fill: '#CCCCCC',\n    d: 'M287.117,660.402c0,0,0-10.595-4.944-9.183c-4.944,1.413-68.507,32.488-79.101,49.438  C203.072,700.659,277.229,655.458,287.117,660.402z'\n  }),\n  createElement('path', {\n    id: 'path138',\n    fill: '#CCCCCC',\n    d: 'M289.235,641.333c0,0,2.119-8.475-2.825-7.063c-3.531,0-50.144,20.481-60.738,37.433  C225.672,671.702,277.935,633.564,289.235,641.333z'\n  }),\n  createElement('path', {\n    id: 'path142',\n    fill: '#CCCCCC',\n    d: 'M263.81,725.378l-17.656,13.419c0,0,18.362-13.419,24.719-11.3  c0,0-12.006,19.774-13.419,28.956c0,0,18.363-22.602,28.25-21.895c0,0,13.419,0.706,13.419,19.774c0,0,9.888-18.362,15.537-17.656  c0,0,2.119,11.302,0,23.308c0,0,7.063-13.419,14.125-10.595c0,0,11.301-3.53,9.888,16.95c0,0,0,18.362-1.412,23.308  c0,0,9.889-46.613,14.125-47.319c0,0,14.125-2.119,22.602,13.419c0,0-7.063-13.419,1.412-9.888c0,0,19.068,2.824,24.719,14.831  c0,0-12.006-21.188-2.118-15.537c0,0,12.006,0,14.125,11.3c0,0,14.831,37.432,18.362,40.257c0,0-13.419-38.138-10.595-38.138  c0,0-3.53-21.188,5.65,4.942c0,0-5.65-24.719,4.237-23.307c9.888,1.413,17.655,19.069,32.487,14.832  c0,0,16.952,9.888,20.483-112.295L263.81,725.378z'\n  }),\n  createElement('path', {\n    id: 'path146',\n    d: 'M272.285,561.526c0,0,26.131-10.595,96.757,0c0,0,12.713,0.706,24.72-14.831  c12.006-15.538,59.325-28.251,70.625-24.721l16.952,11.302l1.413,2.118c0,0,21.895,18.362,22.6,31.781  c0.706,13.418-25.425,98.169-42.377,126.42c-16.949,28.25-33.899,50.145-67.801,45.906c0,0-36.726-7.063-81.926,0  c0,0-51.557-2.825-56.5-16.95s19.775-40.963,19.775-40.963s7.769-14.831,5.65-40.257C280.054,615.908,280.76,566.47,272.285,561.526  z'\n  }),\n  createElement('path', {\n    id: 'path150',\n    fill: '#E5668C',\n    d: 'M311.129,565.058c14.832,32.487-37.431,147.607-37.431,147.607  c-3.531,2.825,22.353,13.499,40.256,9.182c19.327-4.657,90.401,2.825,90.401,2.825c41.669-27.544,64.27-105.938,64.27-105.938  s18.364-42.376-12.713-48.025C424.837,565.058,311.129,565.058,311.129,565.058z'\n  }),\n  createElement('path', {\n    id: 'path154',\n    fill: '#B23259',\n    d: 'M307.543,619.608c5.873-22.582,8.67-43.419,3.586-54.552c0,0,110.177,11.301,129.951-25.426  c7.488-13.904,33.55,40.257,32.842,57.207c0,0-111.236,25.426-137.367,5.65L307.543,619.608z'\n  }),\n  createElement('path', {\n    id: 'path158',\n    fill: '#A5264C',\n    d: 'M315.367,648.396c0,0,3.531,12.713-0.707,19.774c0,0-2.824,1.413-4.943,2.119  c0,0,2.119,6.356,12.713,9.182c0,0,3.531,7.77,7.77,8.476s12.713,10.594,19.774,8.475c7.063-2.118,26.839-9.181,26.839-9.181  s9.888-5.65,25.425,0.706c0,0,4.192-1.416,4.942-8.476c0.884-8.299,6.356-14.832,9.889-18.362  c3.531-3.531,20.48-26.133,18.362-26.838C433.313,633.564,315.367,648.396,315.367,648.396z'\n  }),\n  createElement('path', {\n    id: 'path162',\n    fill: '#FF727F',\n    stroke: '#000000',\n    d: 'M307.598,562.938c0,0-4.943,39.552,0.707,54.383  c5.649,14.832,4.237,18.362,2.824,25.426c-1.412,7.063,6.356,24.719,16.244,35.313l21.188,2.825c0,0,26.839-6.355,43.082-1.412  c0,0,15.881,2.371,21.895-24.014c0,0,8.476-11.3,21.188-16.243c12.713-4.943,25.426-78.395,18.362-92.52  c-7.063-14.126-32.488-21.896-60.738,5.648S360.567,550.227,307.598,562.938z'\n  }),\n  createElement('path', {\n    id: 'path166',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M310.423,695.009c0,0-1.412-3.531-9.181-4.237  c0,0-39.55-6.355-54.382-28.25c0,0-12.006-9.888-4.238,10.595c0,0,18.363,36.019,30.369,40.963  C272.991,714.078,301.948,721.141,310.423,695.009z'\n  }),\n  createElement('path', {\n    id: 'path170',\n    fill: '#CC3F4C',\n    d: 'M451.572,582.058c1.163-13.96,4.61-29.169,1.515-35.361  c-11.382-22.768-41.35-13.253-60.738,5.648c-28.25,27.544-31.78-2.118-84.751,10.595c0,0-3.081,24.653-1.598,42.332  c0,0,65.867-20.438,67.28-10.551c0,0,2.823-5.649,19.067-5.649S448.747,587.001,451.572,582.058z'\n  }),\n  createElement('path', {\n    id: 'path174',\n    stroke: '#A51926',\n    'stroke-width': '2',\n    d: 'M375.398,564.352c0,0,8.476,8.476,2.118,25.426  c0,0-25.426,28.25-21.895,52.97'\n  }),\n  createElement('path', {\n    id: 'path178',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M290.648,714.078c0,0-7.769-22.602,7.769-10.594  c0,0,8.475,3.53,6.356,6.354C302.654,712.665,292.767,719.729,290.648,714.078z'\n  }),\n  createElement('path', {\n    id: 'path182',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M299.547,716.196c0,0-6.215-18.08,6.215-8.476  c0,0,7.806,4.322,5.084,5.085C302.795,715.066,310.847,719.587,299.547,716.196z'\n  }),\n  createElement('path', {\n    id: 'path186',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M308.021,716.196c0,0-6.215-18.08,6.215-8.476  c0,0,7.725,4.078,5.086,5.085C313.39,715.066,319.322,719.587,308.021,716.196z'\n  }),\n  createElement('path', {\n    id: 'path190',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M319.675,716.55c0,0-6.215-18.08,6.215-8.476  c0,0,7.739,4.118,5.087,5.085C325.749,715.066,330.977,719.939,319.675,716.55z'\n  }),\n  createElement('path', {\n    id: 'path194',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M331.116,716.408c0,0-6.215-18.08,6.217-8.476  c0,0,6.78,2.825,5.085,5.085C340.723,715.278,342.418,719.799,331.116,716.408z'\n  }),\n  createElement('path', {\n    id: 'path198',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M342.911,717.609c0,0-8.477-21.896,7.769-10.595  c0,0,8.476,3.531,6.356,6.355C354.917,716.196,357.036,721.847,342.911,717.609z'\n  }),\n  createElement('path', {\n    id: 'path202',\n    stroke: '#A5264C',\n    'stroke-width': '2',\n    d: 'M292.767,687.24c0,0,23.307-4.944,33.9,0.706  c0,0,10.594,2.119,12.713,1.412c2.118-0.706,7.77-1.412,7.77-1.412'\n  }),\n  createElement('path', {\n    id: 'path206',\n    stroke: '#A5264C',\n    'stroke-width': '2',\n    d: 'M352.799,702.777c0,0,21.188-24.014,42.375-16.243  c12.389,4.543,10.594-1.413,12.006-6.356c1.413-4.943,1.768-12.358,10.596-17.656'\n  }),\n  createElement('path', {\n    id: 'path210',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M383.168,674.527c0,0-7.063-19.069-12.007,3.53  c-4.944,22.602-10.594,28.957-13.419,33.9c0,0,0,9.182,14.831,8.476c0,0,19.068-0.707,19.774-5.649  C393.055,709.84,390.23,689.358,383.168,674.527z'\n  }),\n  createElement('path', { id: 'path214', stroke: '#A5264C', 'stroke-width': '2', d: 'M407.887,687.24c0,0,6.356-4.237,10.594-2.119' }),\n  createElement('path', { id: 'path218', stroke: '#A5264C', 'stroke-width': '2', d: 'M419.363,658.283c0,0,5.12-8.651,13.596-10.063' }),\n  createElement('path', {\n    id: 'path222',\n    fill: '#B2B2B2',\n    d: 'M279.348,723.259c0,0,31.781,5.65,39.551,2.825c0,0,15.536,0,0.706,3.531  c0,0-22.602,0-36.727-2.118C282.879,727.497,262.397,717.609,279.348,723.259z'\n  }),\n  createElement('path', {\n    id: 'path226',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M304.066,558.701c0,0,31.075,0,34.606,1.412  c0,0,12.713,54.382,6.356,67.801c0,0-2.118,4.944-7.063-4.943c0,0-32.488-57.913-38.138-61.443  C294.177,557.996,301.948,558.701,304.066,558.701z'\n  }),\n  createElement('path', {\n    id: 'path230',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M167.936,553.934c0,0,15.714,3.002,37.961,7.594  c0,0,8.475,39.551,14.125,48.024c5.65,8.475-0.706,8.476-7.063,3.531s-32.488-29.663-36.019-37.432  C173.409,567.882,167.936,553.934,167.936,553.934z'\n  }),\n  createElement('path', {\n    id: 'path234',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M206.534,561.909c0,0,10.241,2.732,12.022,6.645  c1.78,3.909-2.123,9.73-2.123,9.73s-1.766,5.835-3.888,2.018C210.424,576.483,205.353,562.958,206.534,561.909z'\n  }),\n  createElement('path', {\n    id: 'path238',\n    d: 'M206.603,561.526c0,0,6.356,9.182,12.713,9.182c6.356,0,7.031-0.729,12.006,0.353  c8.122,1.767,7.416-1.766,19.069,0.354c4.661,0.848,9.181-0.706,14.125,1.412c4.944,2.119,10.594,0.706,12.713-2.825  s10.594-10.946,10.594-10.946s-22.6,3.179-27.544,4.591C260.279,563.645,220.729,565.764,206.603,561.526z'\n  }),\n  createElement('path', {\n    id: 'path242',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M285.351,561.879c0,0-11.389,6.182-12.095,10.418  c-0.707,4.237,9.27,10.771,9.27,10.771s4.855,8.122,5.915,3.884C289.5,582.714,286.763,562.586,285.351,561.879z'\n  }),\n  createElement('path', {\n    id: 'path246',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M219.166,571.527c0,0,12.372,19.754,12.755-0.041  c0,0,0.983-2.223-2.124-2.261C219.07,569.092,221.756,561.85,219.166,571.527z'\n  }),\n  createElement('path', {\n    id: 'path250',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M231.839,571.967c0,0,13.986,19.752,12.863-0.164  c0,0,0.012-0.587-3.083-0.855C233.238,570.215,233.847,562.238,231.839,571.967z'\n  }),\n  createElement('path', {\n    id: 'path254',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M244.575,571.98c0,0,14.054,18.766,12.873,1.697  c0,0,0.21-2.177-2.71-2.708C247.866,569.725,247.494,563.987,244.575,571.98z'\n  }),\n  createElement('path', {\n    id: 'path258',\n    fill: '#FFFFCC',\n    stroke: '#000000',\n    'stroke-width': '0.5',\n    d: 'M256.716,572.122c0,0,13.948,20.412,14.563,3.143  c0,0,2.903-2.433-0.18-2.824C260.826,571.133,262.235,563.269,256.716,572.122z'\n  }),\n  createElement('path', {\n    id: 'path262',\n    fill: '#E5E5B2',\n    d: 'M192.845,578.354l-13.521-2.702c-4.591-8.828-8.299-19.688-8.299-19.688  s11.212,1.767,33.282,6.709c0,0,1.547,5.858,4.146,16.091L192.845,578.354z'\n  }),\n  createElement('path', {\n    id: 'path266',\n    fill: '#E5E5B2',\n    d: 'M307.732,570.123c-2.942-4.425-5.268-7.528-6.416-8.245c-5.32-3.325,1.995-2.659,3.989-2.659  c0,0,29.258,0,32.583,1.329c0,0,0.926,3.959,2.134,9.946C340.022,570.494,322.21,566.945,307.732,570.123z'\n  }),\n  createElement('path', {\n    id: 'path270',\n    fill: '#CC7226',\n    d: 'M402.378,326.201c48.945,6.992,94.004-55.936,97.112-73.028  c3.106-17.092-14.762-38.067-14.762-38.067c2.33-5.438-6.216-30.298-15.537-46.613c-9.322-16.314-37.398-14.595-68.367-16.314  c-27.968-1.554-60.599,39.621-62.928,42.729c-2.331,3.108,8.546,70.698,10.876,80.798s-2.33,56.712-2.33,56.712  C406.897,316.349,353.434,319.209,402.378,326.201z'\n  }),\n  createElement('path', {\n    id: 'path274',\n    fill: '#EA8E51',\n    d: 'M339.182,196.051c-2.288,3.051,8.392,69.413,10.68,79.328  c2.288,9.916-2.288,55.682-2.288,55.682c57.687-15.679,6.864-12.967,54.918-6.102c48.056,6.865,92.296-54.918,95.347-71.701  c3.051-16.781-14.492-37.375-14.492-37.375c2.288-5.339-6.103-29.748-15.255-45.766c-9.153-16.018-36.717-14.328-67.125-16.018  C373.506,152.573,341.47,193,339.182,196.051z'\n  }),\n  createElement('path', {\n    id: 'path278',\n    fill: '#EFAA7C',\n    d: 'M340.467,197.195c-2.245,2.995,8.235,68.127,10.481,77.859s-2.246,54.65-2.246,54.65  c55.448-16.173,6.737-12.727,53.9-5.989c47.166,6.738,90.587-53.901,93.581-70.373c2.994-16.47-14.224-36.683-14.224-36.683  c2.245-5.24-5.989-29.197-14.973-44.918c-8.984-15.721-36.037-14.063-65.882-15.721C374.155,154.522,342.713,194.2,340.467,197.195z  '\n  }),\n  createElement('path', {\n    id: 'path282',\n    fill: '#F4C6A8',\n    d: 'M341.753,198.339c-2.204,2.938,8.079,66.842,10.282,76.391  c2.204,9.548-2.203,53.619-2.203,53.619c51.974-15.961,6.61-12.487,52.885-5.876c46.275,6.611,88.877-52.884,91.815-69.043  c2.938-16.161-13.956-35.993-13.956-35.993c2.203-5.142-5.876-28.646-14.69-44.07c-8.813-15.425-35.355-13.799-64.638-15.425  C374.806,156.472,343.956,195.401,341.753,198.339z'\n  }),\n  createElement('path', {\n    id: 'path286',\n    fill: '#F9E2D3',\n    d: 'M343.038,199.483c-2.161,2.881,7.924,65.557,10.085,74.921  c2.161,9.365-2.161,52.588-2.161,52.588c49.205-15.75,6.483-12.246,51.868-5.763c45.386,6.483,87.168-51.868,90.049-67.718  c2.882-15.849-13.687-35.299-13.687-35.299c2.161-5.042-5.765-28.095-14.408-43.223c-8.646-15.128-34.677-13.534-63.396-15.128  C375.455,158.421,345.199,196.602,343.038,199.483z'\n  }),\n  createElement('path', {\n    id: 'path290',\n    fill: '#FFFFFF',\n    d: 'M402.942,319.984c44.493,6.356,85.459-50.85,88.283-66.388  c2.825-15.538-13.419-34.606-13.419-34.606c2.119-4.944-5.65-27.544-14.127-42.375c-8.475-14.831-33.995-13.267-62.149-14.831  c-25.427-1.413-55.088,36.019-57.207,38.844c-2.119,2.825,7.769,64.27,9.888,73.451c2.119,9.182-2.119,51.557-2.119,51.557  C397.116,310.45,358.448,313.628,402.942,319.984z'\n  }),\n  createElement('path', {\n    id: 'path294',\n    fill: '#CCCCCC',\n    d: 'M484.87,259.953c0,0-49.087,13.419-69.568,10.594c0,0-27.896-11.653-43.435,26.838  c0,0-6.356,12.713-9.889,16.244C358.447,317.16,484.87,259.953,484.87,259.953z'\n  }),\n  createElement('path', {\n    id: 'path298',\n    d: 'M491.58,256.068c0,0-51.206,21.541-68.862,20.834c0,0-28.956-8.122-43.788,17.656  c0,0-14.831,16.244-20.48,19.069c0,0-0.706,2.825,10.594-4.238l18.363,9.182c0,0,26.131,16.95,43.081-11.3  c0,0,7.063-19.775,7.063-23.307c0-3.532,37.433-13.419,40.259-14.125C480.633,269.134,492.286,261.718,491.58,256.068z'\n  }),\n  createElement('path', {\n    id: 'path302',\n    fill: '#99CC32',\n    d: 'M407.887,319.479c-12.134,0-26.918-6.824-26.918-17.857c0-11.032,14.784-22.094,26.918-22.094  c12.138,0,21.976,8.943,21.976,19.975C429.861,310.537,420.023,319.479,407.887,319.479z'\n  }),\n  createElement('path', {\n    id: 'path306',\n    fill: '#659900',\n    d: 'M401.489,290.021c-8.557,1.275-17.541,3.929-17.414,3.547  c2.719-8.156,13.95-14.041,23.812-14.041c7.585,0,14.273,3.493,18.222,8.807C426.107,288.335,416.722,287.753,401.489,290.021z'\n  }),\n  createElement('path', { id: 'path310', fill: '#FFFFFF', d: 'M422.718,289.616c0,0-7.769-5.65-7.769-1.766C414.949,287.85,421.306,295.619,422.718,289.616z  ' }),\n  createElement('path', {\n    id: 'path314',\n    d: 'M405.063,303.963c-4.412,0-7.989-3.577-7.989-7.991c0-4.412,3.577-7.989,7.989-7.989  c4.413,0,7.99,3.577,7.99,7.989C413.053,300.386,409.476,303.963,405.063,303.963z'\n  }),\n  createElement('path', {\n    id: 'path318',\n    fill: '#CC7226',\n    d: 'M221.435,280.434c0,0-5.65-37.432-1.413-45.2c0,0,19.069-17.657,18.363-24.013  c0,0-0.706-31.782-2.825-33.194c-2.119-1.413-15.538-12.006-26.131-0.706c0,0-18.363,31.781-16.95,43.082v3.531  c0,0-13.419-0.706-16.244,2.825c0,0-2.119,9.181-4.238,9.888c0,0-4.944,4.237-1.413,9.181c0,0-3.531,4.237-2.825,11.3l13.419,7.063  c0,0,3.531,25.425,22.601,34.606C212.317,302.909,217.903,291.028,221.435,280.434z'\n  }),\n  createElement('path', {\n    id: 'path322',\n    fill: '#FFFFFF',\n    d: 'M219.669,277.186c0,0-5.085-33.688-1.271-40.681c0,0,17.162-15.891,16.527-21.611  c0,0-0.636-28.604-2.543-29.875c-1.907-1.271-13.984-10.806-23.518-0.636c0,0-16.526,28.604-15.255,38.773v3.178  c0,0-12.077-0.636-14.62,2.542c0,0-1.907,8.263-3.813,8.899c0,0-4.45,3.813-1.271,8.263c0,0-3.178,3.813-2.542,10.17l12.077,6.356  c0,0,3.178,22.883,20.34,31.146C211.462,297.411,216.491,286.72,219.669,277.186z'\n  }),\n  createElement('path', {\n    id: 'path326',\n    fill: '#EB955C',\n    d: 'M234.765,179.775c-1.924-1.519-15.149-11.706-25.478-0.688c0,0-17.904,30.987-16.526,42.004  v3.443c0,0-13.083-0.688-15.838,2.754c0,0-2.066,8.952-4.132,9.641c0,0-4.82,4.132-1.377,8.952c0,0-3.443,4.132-2.754,11.018  l13.083,6.886c0,0,3.443,24.79,22.035,33.741c8.323,4.008,13.772-7.574,17.215-17.903c0,0-5.509-36.496-1.377-44.07  c0,0,18.592-17.215,17.903-23.413C237.52,212.139,236.831,181.152,234.765,179.775z'\n  }),\n  createElement('path', {\n    id: 'path330',\n    fill: '#F2B892',\n    d: 'M233.971,181.523c-1.73-1.625-14.761-11.406-24.825-0.671c0,0-17.444,30.192-16.103,40.927  v3.355c0,0-12.748-0.671-15.432,2.684c0,0-2.013,8.722-4.026,9.394c0,0-4.696,4.025-1.342,8.722c0,0-3.354,4.025-2.684,10.735  l12.748,6.709c0,0,3.354,24.154,21.47,32.876c8.111,3.906,13.419-7.38,16.773-17.445c0,0-5.368-35.56-1.342-42.94  c0,0,18.115-16.773,17.444-22.812C236.654,213.057,235.983,182.865,233.971,181.523z'\n  }),\n  createElement('path', {\n    id: 'path334',\n    fill: '#F8DCC8',\n    d: 'M233.176,183.271c-1.536-1.73-14.373-11.106-24.172-0.653c0,0-16.985,29.398-15.679,39.851  v3.266c0,0-12.413-0.653-15.026,2.613c0,0-1.96,8.493-3.919,9.146c0,0-4.573,3.92-1.307,8.493c0,0-3.267,3.92-2.613,10.453  l12.413,6.533c0,0,3.266,23.518,20.905,32.011c7.897,3.803,13.065-7.186,16.332-16.985c0,0-5.227-34.624-1.307-41.811  c0,0,17.639-16.332,16.985-22.211C235.789,213.976,235.136,184.578,233.176,183.271z'\n  }),\n  createElement('path', {\n    id: 'path338',\n    fill: '#FFFFFF',\n    d: 'M219.669,277.009c0,0-5.085-33.512-1.271-40.504c0,0,17.162-15.891,16.527-21.611  c0,0-0.636-28.604-2.543-29.875c-1.342-1.836-13.984-10.806-23.518-0.636c0,0-16.526,28.604-15.255,38.773v3.178  c0,0-12.077-0.636-14.62,2.542c0,0-1.907,8.263-3.813,8.899c0,0-4.45,3.813-1.271,8.263c0,0-3.178,3.813-2.542,10.17l12.077,6.356  c0,0,3.178,22.883,20.34,31.146C211.462,297.411,216.491,286.543,219.669,277.009z'\n  }),\n  createElement('path', {\n    id: 'path342',\n    fill: '#CCCCCC',\n    d: 'M214.195,265.956c0,0-38.138-18.01-39.727-19.422c0,0,16.067,14.479,17.48,14.479  C193.361,261.013,214.195,265.956,214.195,265.956z'\n  }),\n  createElement('path', {\n    id: 'path346',\n    d: 'M184.003,255.009c0,0,32.488,6.356,32.488,14.125c0,5.141-0.429,28.834-9.888,26.131  C191.772,291.028,198.128,265.603,184.003,255.009z'\n  }),\n  createElement('path', {\n    id: 'path350',\n    fill: '#99CC32',\n    d: 'M198.834,261.718c0,0,15.852,2.603,17.656,7.416c1.06,2.825,2.23,17.494-7.416,19.422  C201.038,290.165,197.101,272.118,198.834,261.718z'\n  }),\n  createElement('path', {\n    id: 'path354',\n    d: 'M350.671,336.845c-0.878-3.076,1.438-2.845,4.601-3.794c3.53-1.06,25.071-7.769,26.483-12.359  c1.413-4.591,24.719,3.178,24.719,3.178c3.18,1.412,10.947,6.003,10.947,6.003c8.476,2.119,20.128,2.825,20.128,2.825  c4.238,1.766,10.241,6.709,10.241,6.709c25.778,18.009,47.674,5.297,47.674,5.297c35.313-11.653,24.72-42.022,24.72-42.022  c-5.298-15.891,0.354-21.894,0.354-21.894c0.354-6.709,13.064,4.591,13.064,4.591c4.592,7.416,6.005,16.244,6.005,16.244  c14.125,19.775,8.122-11.653,8.122-11.653c0.353-1.766-4.592-8.122-4.592-10.241s-3.179-8.122-3.179-8.122  c-5.297-6.003-1.06-18.363-1.06-18.363c3.179-24.366-0.706-21.188-0.706-21.188c-2.118-3.178-18.362,14.478-18.362,14.478  c-3.885,6.003-14.479,8.828-14.479,8.828c-4.942,3.178-10.946,0.707-10.946,0.707c-4.59-0.707-14.479,11.653-14.479,11.653  c4.943-0.354,9.182,7.416,13.419,7.769c4.237,0.354,7.415-4.237,10.24-5.297c2.825-1.059,7.769,9.182,7.769,9.182  c0.707,4.59-9.181,13.065-9.181,13.065c-0.707,8.122-3.531,5.297-3.531,5.297c-5.297-1.059-7.415,5.65-9.182,13.772  c-1.766,8.122-9.182,8.829-9.182,8.829c-2.825,13.065-4.945,7.769-4.945,7.769c-0.354-9.888-10.947,0.353-10.947,0.353  c-2.118,3.531-10.239-0.353-10.239-0.353c-12.008-3.531-7.77-7.063-7.77-7.063c3.178-3.884,22.953,0,22.953,0  c3.884-2.825-10.241-9.888-10.241-9.888c-1.06-3.178,0.706-10.947,0.706-10.947c2.119-5.65,14.126-15.538,14.126-15.538  c16.599-2.119,11.654-4.944,11.654-4.944c-10.946-9.182-21.189,4.237-21.189,4.237c-3.884,10.947-34.605,37.432-34.605,37.432  c-8.476,6.003-3.884-6.003-10.947,0c-7.063,6.003-43.435-9.888-43.435-9.888c-20.414-2.106-25.238,25.688-31.47,20.18  C343.93,331.689,353.496,346.732,350.671,336.845z'\n  }),\n  createElement('path', {\n    id: 'path358',\n    d: 'M694.629,43.132c0,0-45.201,14.125-50.145,47.319c0,0-4.237,40.256,31.78,71.332c0,0,0.707,11.3,4.238,16.95  c0,0-2.825,8.475,30.368-4.944l48.025-14.832c0,0,11.301-4.238,20.481-19.775c9.181-15.538,36.019-48.731,29.662-93.226  c0,0,2.119-19.775-8.475-20.481c0,0-14.832-2.825-27.544,10.594c0,0-12.008,5.65-16.244,4.944L694.629,43.132z'\n  }),\n  createElement('path', {\n    id: 'path362',\n    d: 'M791.069,41.384c0,0,3.708-15.767-4.837-7.222c0,0-12.432,10.1-25.641,10.1c0,0-25.637,3.884-33.404,27.191  c0,0-6.992,47.39,6.99,57.489c0,0,8.546,13.207,20.978,1.554C767.587,118.843,794.954,65.467,791.069,41.384z'\n  }),\n  createElement('path', {\n    id: 'path366',\n    fill: '#323232',\n    d: 'M790.409,42.016c0,0,3.689-15.438-4.7-7.048c0,0-12.204,9.916-25.173,9.916  c0,0-25.171,3.814-32.798,26.697c0,0-6.865,46.528,6.863,56.444c0,0,8.392,12.967,20.596,1.525  C767.403,118.108,794.224,65.661,790.409,42.016z'\n  }),\n  createElement('path', {\n    id: 'path370',\n    fill: '#666666',\n    d: 'M789.749,42.648c0,0,3.673-15.11-4.563-6.875c0,0-11.978,9.732-24.705,9.732  c0,0-24.705,3.743-32.191,26.202c0,0-6.738,45.667,6.737,55.399c0,0,8.234,12.727,20.213,1.497  C767.22,117.374,793.492,65.855,789.749,42.648z'\n  }),\n  createElement('path', {\n    id: 'path374',\n    fill: '#999999',\n    d: 'M789.089,43.28c0,0,3.654-14.782-4.425-6.703c0,0-11.752,9.549-24.24,9.549  c0,0-24.239,3.672-31.584,25.708c0,0-6.609,44.805,6.61,54.354c0,0,8.08,12.487,19.832,1.469  C767.036,116.639,792.762,66.05,789.089,43.28z'\n  }),\n  createElement('path', {\n    id: 'path378',\n    fill: '#CCCCCC',\n    d: 'M788.429,43.912c0,0,3.638-14.454-4.287-6.529c0,0-11.527,9.365-23.773,9.365  c0,0-23.772,3.602-30.978,25.213c0,0-6.482,43.943,6.483,53.309c0,0,7.924,12.247,19.45,1.441  C766.851,115.904,792.03,66.244,788.429,43.912z'\n  }),\n  createElement('path', {\n    id: 'path382',\n    fill: '#FFFFFF',\n    d: 'M787.767,44.544c0,0,3.619-14.125-4.148-6.356c0,0-11.301,9.181-23.308,9.181  c0,0-23.307,3.531-30.368,24.719c0,0-6.356,43.082,6.355,52.263c0,0,7.77,12.006,19.069,1.412  C766.667,115.17,791.298,66.438,787.767,44.544z'\n  }),\n  createElement('path', {\n    id: 'path386',\n    fill: '#992600',\n    d: 'M414.243,403.323c0,0-36.021-33.901-50.146-35.313c0,0-60.738-7.063-86.87,24.719  c0,0,31.076-36.019,79.807-26.131c0,0-38.138-7.769-60.032-2.119c0,0-29.663,0-46.613,24.719l-4.944,8.475  c0,0,7.063-26.131,39.55-36.726c0,0,40.256-8.475,59.326,0c0,0-38.138-12.006-55.794-8.475c0,0-53.675-4.237-76.275,42.375  c0,0,7.063-25.425,33.194-38.138c0,0,24.013-15.538,60.032-10.594c0,0,25.425,5.65,34.607,9.888  c9.182,4.237,7.063-0.707-7.769-9.182c0,0-9.889-17.656-34.607-16.95c0,0-75.57,6.356-93.932,27.544  c0,0,24.013-19.775,42.375-24.719c0,0,39.55-14.125,54.381-12.713c0,0,43.788,1.766,57.207-5.297c0,0-19.775,8.828-14.125,14.479  c5.649,5.65,17.656,19.069,17.656,21.188s42.729,41.14,49.085,48.908L414.243,403.323z'\n  }),\n  createElement('path', {\n    id: 'path390',\n    fill: '#CCCCCC',\n    d: 'M658.607,745.857c0,0-27.367-64.445-49.438-81.221c0,0,45.906,28.251,52.086,60.032  C661.256,724.67,661.256,742.326,658.607,745.857z'\n  }),\n  createElement('path', {\n    id: 'path394',\n    fill: '#CCCCCC',\n    d: 'M741.593,759.1c0,0-46.789-97.109-79.454-139.484c0,0,76.807,66.212,85.635,113.001  l0.883,9.711l-5.297-4.414C743.358,737.912,742.476,753.803,741.593,759.1z'\n  }),\n  createElement('path', {\n    id: 'path398',\n    fill: '#CCCCCC',\n    d: 'M841.352,673.466c0,0-110.353-105.056-113.001-109.47c0,0,106.821,116.533,112.118,129.775  C840.469,693.771,836.938,677.88,841.352,673.466z'\n  }),\n  createElement('path', {\n    id: 'path402',\n    fill: '#CCCCCC',\n    d: 'M508.528,750.271c0,0,34.43-91.813,67.977-52.087c0,0,26.485,17.656,25.604,22.953  c0,0-7.063-11.477-38.846-10.594C563.263,710.545,529.716,705.248,508.528,750.271z'\n  }),\n  createElement('path', {\n    id: 'path406',\n    fill: '#CCCCCC',\n    d: 'M844.883,525.152c0,0-79.454-50.321-92.695-52.971c-20.848-4.168,87.398,51.204,96.228,69.743  C848.414,541.926,851.945,537.512,844.883,525.152z'\n  }),\n  createElement('path', {\n    id: 'path410',\n    d: 'M578.803,713.371c0,0,36.02-3.531,48.025-15.537l7.769,6.356l31.075-67.802l6.356,9.183  c0,0,25.426-26.132,24.013-40.257c-1.412-14.125,22.601,10.594,22.601,10.594s-1.413-20.481,11.301-8.477  c0,0-4.237-27.544,10.594-13.419c0,0-18.604-53.246,21.188-7.769c9.889,11.3,2.119-0.706,2.119-0.706s-45.905-84.751-7.769-59.325  c0,0,3.531-40.257,1.412-48.026c-2.118-7.769-5.649-47.319-14.125-56.502c-8.477-9.182,0.706-12.006,10.594-2.824  c0,0-19.775-42.375,3.531-21.188c0,0-6.356-26.838-14.125-31.782c0,0-9.889-30.369,16.949-11.3c0,0-7.769-21.894-13.419-27.544  c0,0-20.48-48.732-7.769-40.257l7.769,6.356c0,0-12.007-24.719-0.706-16.95s11.301,7.063,11.301,7.063s-37.433-58.62-1.412-27.544  c0,0-14.406-24.574-20.481-36.726c0,0-33.193-36.019-7.77-24.719l8.476,2.825c0,0-15.538-17.656-29.663-20.481  c-14.125-2.825,4.237-14.125,15.538-10.594c11.3,3.531,38.844,16.95,38.844,16.95s22.602,33.194,29.663,33.9  c0,0-35.313-13.419-24.719,0.706c0,0,25.425,24.719,12.712,24.013c0,0-10.594,12.713-2.118,28.25c0,0-32.592-32.472-6.355,12.712  l12.006,28.957c0,0-43.081-43.788-23.306-4.944c0,0,30.369,41.669,33.899,42.375c3.531,0.707,11.3,16.244,11.3,16.244l-7.769-3.531  l9.181,15.538c0,0-19.774-21.188-9.181,2.119l9.887,25.425c0,0-36.019-38.844-12.006,13.42c0,0-28.957-9.183-13.419,21.188  c0,0-2.825,28.252-2.119,37.434c0.707,9.183,2.825,59.325-4.942,73.451c-7.77,14.125,10.594,48.025,14.125,55.088  c3.53,7.063,9.888,26.131-5.65,9.889c-15.537-16.244-7.769-6.356-4.237,9.181c3.531,15.538,14.125,43.082,12.713,52.97  c0,0-2.118,2.119-7.769-4.236c0,0-26.132-40.258-23.307-14.832c0,0-2.119,14.125-7.77,29.663c0,0-5.649,19.068-5.649,3.53  c0,0-5.65-29.663-10.595-16.244c-4.943,13.42-11.301,24.014-16.244,28.251c-4.942,4.237-14.125-36.02-16.243-17.656  c0,0-21.188-21.895-29.662,7.063l-20.482,28.957c0,0-0.706-21.894-2.824-11.3C650.135,710.547,597.165,721.141,578.803,713.371z'\n  }),\n  createElement('path', {\n    id: 'path414',\n    d: 'M518.064,83.389c0,0-20.481-14.125-27.545-13.419c-7.063,0.706,48.731-15.538,121.477,33.194  c0,0,8.476,4.944,14.832,4.238c0,0,5.648,4.237,0.706,10.594c0,0-15.538,16.95,4.237,36.725c0,0,32.487,12.006,22.601-3.531  c0,0,19.069,7.063,23.307,14.125c4.238,7.062,2.118,0,2.118,0s-11.3-12.713-21.894-21.894c0,0-9.183-3.531-14.125-18.363  c-4.944-14.832-9.183-32.488-1.413-38.138c0,0-7.063,7.769-5.649,0.706c1.412-7.063,7.77-13.419,10.594-14.125  c2.825-0.707,31.781-28.604,43.788-29.31c0,0-16.244,2.472-21.541,0.706S617.293,23.003,606.7,20.884c0,0-29.662-11.653-8.476-8.122  c0,0,63.211,6.709,95.346,30.016c0,0-12.713-14.832-45.2-27.191c0,0-39.197-22.247-101.349-13.419c0,0-31.429,5.65-45.2,8.828  c0,0-4.591-1.06-5.65-1.766c-1.059-0.706-21.896-16.597-70.627-4.237c0,0-30.016,8.122-45.2,16.597c0,0-26.838,2.119-33.193,7.769  c0,0-32.842,25.778-36.372,27.191c-3.531,1.413-23.66,14.831-25.072,15.538c0,0,43.435-11.653,47.672-15.891  c4.238-4.237,34.96-8.828,39.197-6.356c4.238,2.472,19.069,1.413,2.119,2.472c0,0,133.483,26.132,134.896,29.663  C511.002,85.507,518.064,83.389,518.064,83.389z'\n  }),\n  createElement('path', {\n    id: 'path418',\n    fill: '#CC7226',\n    d: 'M644.131,67.145c0,0-18.009-13.066-21.54-13.066c-3.532,0-25.426-18.009-32.842-17.303  c-7.415,0.707-28.956-16.95-77.335-2.472c0,0-1.061-3.531,5.297-4.944c0,0,11.301-3.884,12.007-4.944c0,0,35.666-7.416,48.378-1.06  c0,0,16.244,4.591,27.191,15.538c0,0,19.775,5.65,25.425,3.885c0,0,15.538,3.884,16.244,7.063c0,0,10.241,5.297,7.063,9.888  C654.019,59.729,654.725,62.554,644.131,67.145z'\n  }),\n  createElement('path', {\n    id: 'path422',\n    fill: '#CC7226',\n    d: 'M622.112,63.421c1.425,1.116,3.224,1.289,4.292,2.717c0.413,0.554-0.099,1.13-0.653,1.301  c-1.842,0.56-3.706-0.447-5.723,0.591c-0.71,0.366-1.844,0.044-2.819-0.219c-2.882-0.779-6.111-0.823-9.097,0.392  c-3.505-1.994-7.672-0.962-11.348-2.73c-0.102-0.047-0.493,0.563-0.625,0.516c-5.378-2.021-11.985-1.522-16.278-5.555  c-4.286-0.728-8.448-1.543-12.735-2.744c-3.21-0.899-5.697-2.645-8.558-4.114c-2.433-1.25-5.004-2.171-7.713-2.828  c-3.289-0.798-6.521-0.601-9.864-1.519c-0.164-0.044-0.503,0.563-0.648,0.516c-0.57-0.191-1.084-1.22-1.386-1.127  c-2.968,0.922-5.595-0.794-8.533-0.19c-2.08-2.161-5.131-1.729-7.859-2.509c-5.233-1.498-10.804,0.745-16.152-1.022  c7.262-3.252,15.538-1.077,22.71-4.73c4.11-2.094,8.811-0.148,13.348-1.49c0.86-0.254,2.08-0.611,2.786,0.57  c0.237-0.239,0.56-0.661,0.661-0.611c4.325,2.042,8.413,4.292,12.795,6.174c0.604,0.258,1.542-0.152,1.986,0.205  c2.684,2.147,6.114,1.965,8.569,4.119c2.998-0.886,6.164-0.215,9.218-1.317c0.137-0.048,0.55,0.554,0.606,0.516  c1.995-1.321,4.035-0.842,5.609-0.306c0.597,0.203,1.768,0.639,2.307,0.77c1.987,0.487,3.499,1.335,5.581,1.658  c0.201,0.032,0.527-0.568,0.655-0.519c1.982,0.773,3.822,0.674,4.979,2.729c0.238-0.238,0.529-0.658,0.676-0.611  c1.813,0.597,2.959,1.93,4.901,2.355c0.856,0.187,1.938,1.292,2.954,1.603c4.224,1.291,7.479,3.991,11.353,5.571  C619.447,62.132,620.994,62.545,622.112,63.421z'\n  }),\n  createElement('path', {\n    id: 'path426',\n    fill: '#CC7226',\n    d: 'M486.804,38.296c-4.445-3.046-8.627-4.999-12.938-8.152c-0.32-0.235-0.955,0.065-1.313-0.15  c-1.776-1.075-3.346-2.101-5.079-3.33c-0.952-0.674-2.4-0.655-3.299-1.11c-4.491-2.281-9.134-3.267-13.56-5.375  c1.204-1.126,3.185-0.695,4.236-2.119c0.346,0.495,0.766,0.996,1.389,0.659c2.963-1.596,6.229-1.866,9.188-1.708  c3.01,0.163,6.046,0.701,9.181,1.181c0.542,0.083,0.894,1.006,1.464,1.178c3.934,1.171,8.15,0.244,11.894,1.723  c2.81,1.111,5.581,2.564,7.77,4.815c0.444,0.459-0.13,0.991-0.623,1.333c0.685-0.193,1.167,0.171,1.361,0.724  c0.148,0.422,0.148,0.955,0,1.377c-0.196,0.551-0.689,0.729-1.351,0.819c-2.484,0.336,0.645-2.101-0.591-1.31  c-2.248,1.438-0.932,3.92-2.246,6.159c-0.494-0.342-0.9-0.728-0.706-1.413c0.413,0.922-0.65,1.434-0.947,1.992  C489.953,36.869,488.366,39.367,486.804,38.296z'\n  }),\n  createElement('path', {\n    id: 'path430',\n    fill: '#CC7226',\n    d: 'M429.424,51.27c-5.568-1.402-10.954-1.199-16.279-3.452c-0.117-0.049-0.512,0.563-0.625,0.516  c-2.411-1.049-4.032-2.754-5.933-4.602c-1.612-1.568-4.539-0.884-6.789-1.744c-0.572-0.219-0.931-1.123-1.462-1.192  c-2.152-0.277-3.789-1.953-5.634-2.961c4.124-1.404,8.381-1.349,12.729-2.027c0.199-0.031,0.455,0.535,0.69,0.535  c0.24,0,0.47-0.39,0.706-0.627c0.345,0.495,0.878,1.07,1.331,0.622c0.968-0.953,1.949-0.618,2.902-0.547  c0.255,0.018,0.476,0.553,0.709,0.553c0.24,0,0.473-0.549,0.707-0.549c0.239,0.001,0.472,0.549,0.706,0.549  c0.24,0,0.471-0.39,0.706-0.627c1.223,1.381,2.784,0.403,4.235,0.719c1.833,0.401,2.305,2.428,4.201,2.954  c8.324,2.302,15.629,6.09,23.333,9.774c0.542,0.26,0.912,0.698,0.719,1.384c0.471,0,1.023-0.155,1.359,0.078  c1.867,1.292,3.706,2.26,4.937,4.199c0.381,0.599-0.199,1.317-0.61,1.226C444.243,54.292,437.17,53.219,429.424,51.27z'\n  }),\n  createElement('path', {\n    id: 'path434',\n    fill: '#CC7226',\n    d: 'M404.952,129.332c-2.813-2.152-3.842-5.738-5.834-8.902c-0.378-0.6,0.105-1.154,0.666-1.312  c0.987-0.281,1.946,0.563,2.669,0.92c3.081,1.522,5.792,3.715,9.316,3.96c3.515,3.945,11.036,4.625,11.049,10.594  c0.002,1.517-2.521-0.104-3.278,1.412c-4.328-1.771-8.546-1.589-12.748-4.179C405.702,131.152,406.285,130.353,404.952,129.332z'\n  }),\n  createElement('path', {\n    id: 'path438',\n    fill: '#CC7226',\n    d: 'M356.33,36.5c0.238,0.002,12.652,0.413,12.622,0.614c-0.079,0.546-13.729,2.398-14.37,2.098  c-0.29-0.134-13.554,4.156-13.79,3.92C341.266,42.894,355.86,36.5,356.33,36.5z'\n  }),\n  createElement('path', {\n    id: 'path442',\n    d: 'M383.521,53.726c0,0-26.133,3.178-33.9,5.297c-7.77,2.119-40.609,15.538-45.907,19.069  c0,0-23.66,9.535-53.675,44.848c0,0,13.419-6.003,17.303-10.947c0,0,24.013-22.247,23.66-17.656c0,0,21.541-15.185,20.481-11.3  c0,0,43.082-19.775,39.551-14.125c0,0,38.138-8.122,36.372-4.591c0,0,33.192,7.769,28.25,8.122c0,0-10.241,2.119,1.06,8.475  c0,0-6.003,7.769-15.538,0.707c-9.534-7.063-4.236-3.178-13.064-1.413c0,0-4.592,1.413-12.713-5.65c0,0-9.889-8.122-25.426-1.766  c0,0-54.029,22.247-57.56,23.307c0,0-6.356,4.944-10.594,11.3c0,0-10.241,7.769-15.538,10.241c0,0-22.6,20.481-24.719,22.953  c0,0-6.003,9.181-7.416,9.888c0,0,11.3-6.709,14.831-10.241c0,0,24.719-17.656,34.253-19.069c0,0,7.769-5.297,9.182-7.769  c0,0,25.425-16.244,32.84-16.244c0,0,16.244,9.181,20.482-3.178c0,0,10.239-3.178,20.128-1.06c0,0,5.649-4.591,4.236-8.475  c0,0,2.825-3.178,4.592,3.531c0,0,6.003,6.356,14.479,2.825c0,0,7.063-0.353,3.531,3.884c0,0-7.77,6.709-28.604,7.063  c0,0-21.895,1.06-50.851,14.479c0,0-52.616,18.363-68.86,36.725c0,0-11.3,15.538-20.834,17.657c0,0-10.241,1.412-20.834,14.478  c0,0,17.303-10.241,33.194-10.241c0,0,7.063-4.237,0.353,2.119c0,0-6.356,13.418-3.531,22.953c0,0-1.06,9.181-2.472,12.006  c0,0-13.772,22.6-13.772,26.838c0,4.237,2.119,21.541,2.825,22.6c0.706,1.06-1.766-2.825,4.944,1.413  c6.709,4.237,11.653,7.063,13.065,12.006c1.413,4.944-3.531-9.535-3.884-12.713c-0.353-3.178-7.769-15.891-6.356-20.128  c0,0,1.766,1.766,3.178,4.237c0,0-1.059-1.06,0-7.416c0,0,1.413-9.182,3.885-14.832s6.003-12.359,6.709-13.772  c0.707-1.413,0.707-11.653,3.178-7.063l6.003,4.59c0,0-4.944-4.59-1.06-8.475c0,0-1.766-9.888,1.413-14.479  c0,0,12.359-14.832,15.185-16.597c2.826-1.765,0.353-1.059,0.353-1.059s10.594-7.416,0.353-4.591c0,0-7.063,2.825-12.359,2.825  c0,0-13.419,3.531-6.356-3.885s24.719-16.95,31.429-16.597l1.413,2.825l19.775-4.237l-2.119,1.413c0,0-0.353-0.354,7.063-1.06  s17.656,1.766,20.128-1.413c2.473-3.178,8.477-4.944,7.771-2.472c-0.706,2.472-1.061,6.003-1.061,6.003s8.828-10.241,7.77-6.356  c-1.061,3.884-15.537,13.065-18.011,24.013l18.363-14.479l6.356-5.297c0,0,6.355,3.884,6.709,1.06  c0.354-2.825,8.476-13.066,10.594-12.713c2.119,0.353,5.649-4.591,5.297,0c-0.353,4.591,13.066,14.125,13.066,14.125  s5.648-3.178,8.122-0.706c2.472,2.472,9.887-34.96,9.887-34.96l44.142-18.716l76.983-6.003l-30.017-12.006L383.521,53.726z'\n  }),\n  createElement('path', {\n    id: 'path446',\n    stroke: '#4C0000',\n    'stroke-width': '2',\n    d: 'M415.655,405.089c0,0-26.484-29.663-41.316-34.254  c0,0-23.659-12.006-67.094,1.766'\n  }),\n  createElement('path', {\n    id: 'path450',\n    stroke: '#4C0000',\n    'stroke-width': '2',\n    d: 'M368.689,368.363c0,0-44.494-14.125-71.687-6.709  c0,0-32.488,3.531-47.319,27.897'\n  }),\n  createElement('path', {\n    id: 'path454',\n    stroke: '#4C0000',\n    'stroke-width': '2',\n    d: 'M362.333,366.245c0,0-30.016-12.713-56.147-16.597  c0,0-29.31-4.591-58.62,8.122c0,0-21.541,10.594-31.075,28.603'\n  }),\n  createElement('path', {\n    id: 'path458',\n    stroke: '#4C0000',\n    'stroke-width': '2',\n    d: 'M364.099,366.951c0,0-27.19-19.422-28.957-21.894  c0,0-12.358-19.422-35.313-20.128c0,0-37.785,1.413-68.154,15.538'\n  }),\n  createElement('path', {\n    id: 'path462',\n    d: 'M361.794,351.072c2.723,2.583,50.33,53.664,50.33,53.664c62.15,64.624,12.713,4.236,12.713,4.236  c-13.419-8.475-29.663-41.669-29.663-41.669c-2.119-4.944,24.719,12.713,24.719,12.713c7.063,1.412,31.075,35.313,31.075,35.313  c-12.006-4.237-3.53,8.476-3.53,8.476c4.943,3.531,40.965,31.077,40.965,31.077c6.355,7.063,13.419,9.888,13.419,9.888  c24.719-9.182,13.419,14.125,13.419,14.125c4.236,12.007,14.125-8.476,14.125-8.476c19.774-29.664-9.182-25.425-9.182-25.425  c-52.972,4.942-64.978-23.31-64.978-23.31c-4.238-4.236,11.3,0,11.3,0c14.833,3.531-12.713-21.894-12.713-21.894  c4.237,0,20.481,12.006,20.481,12.006c18.363,16.244,21.896,12.713,21.896,12.713c31.782-15.538,50.146-2.119,50.146-2.119  c3.53,2.825-6.356,14.832-3.531,24.016c2.825,9.182,11.3,31.075,11.3,31.075c-4.237,2.824-3.531,21.895-3.531,21.895  c29.663,40.963,12.713,37.432,12.713,37.432c-27.544-0.707-1.411,12.712-1.411,12.712c5.648,3.531,21.188,16.244,21.188,16.244  c-4.944-2.119-7.769,7.063-7.769,7.063c8.475,7.063,3.53,15.538,3.53,15.538c-10.594,2.118-12.713,9.181-12.713,9.181  c12.006,14.126-5.649,14.832-5.649,14.832c6.355,7.769-2.118,28.956-2.118,28.956c-8.477,0-19.775,9.888-19.775,9.888  c4.237,8.477-14.125,18.363-14.125,18.363c-14.832,2.824-9.888,14.831-9.888,14.831c-14.125,10.594-18.363,38.844-18.363,38.844  c-1.412,18.363-5.648,24.014,3.531,20.481c9.182-3.531,7.77-25.425,7.77-25.425c-8.476-27.545,67.095-55.795,67.095-55.795  c7.063-2.824,8.476-12.007,8.476-12.007c3.531,0.706,19.069,14.125,19.069,14.125c13.418,19.775,14.125,3.531,14.125,3.531  c2.118-6.356-0.707-16.95-0.707-16.95c10.595-38.138-14.125-49.438-14.125-49.438c-17.656-59.326,7.063-44.494,7.063-44.494  c4.944,9.888,24.014,19.068,24.014,19.068l6.355-4.237c-2.824-8.477,12.007-19.069,12.007-19.069  c4.943,11.301,15.537-2.824,15.537-2.824c6.356-43.082,28.251-17.656,28.251-17.656c7.063,2.119,9.182-9.889,9.182-9.889  c6.355-18.361,0-42.375,0-42.375c6.355-0.706,23.307,9.889,23.307,9.889c4.944-6.356-11.3-36.021-4.237-31.781  c7.063,4.237,14.831,7.063,14.831,7.063c1.413-3.53-16.243-25.426-16.243-25.426c-7.77-4.945-16.949-40.965-16.949-40.965  c12.712,6.356-4.944-20.481-4.944-20.481c0-5.65,10.594-25.425,10.594-25.425c-1.412-12.006,0-11.3,0-11.3  c4.944,2.119,19.069,4.944,7.063-6.356c-12.006-11.3,1.413-19.775,1.413-19.775c7.769-4.944-16.244-4.238-16.244-4.238  c-9.183-7.769-8.477-14.831-8.477-14.831c14.126,3.531-11.3-21.894-15.536-28.25c-4.237-6.356,12.713-15.538,12.713-15.538  c23.307-6.356,2.823-12.006,2.823-12.006c-34.605,0.706-15.536-18.363-15.536-18.363c10.594,0.707,7.769-3.531,7.769-3.531  c-9.181-2.119-26.132-13.419-26.132-13.419c-7.063-6.356-0.706-4.944-0.706-4.944c29.663,2.119-21.188-17.656-21.188-17.656  c14.125,0-17.655-18.363-17.655-18.363c-3.531-2.825-9.183-16.244-9.183-16.244c-10.594-9.182-19.067-21.188-19.067-21.188  c-0.707-7.769-9.183-16.244-9.183-16.244c-20.48-24.013-30.369-23.307-30.369-23.307c-26.132-6.356-35.313-4.944-35.313-4.944  l-93.229,7.769c-46.612,22.6-32.842,59.679-32.842,59.679c11.301,14.831,27.544,8.122,27.544,8.122  c8.122-10.947,28.604-7.063,28.604-7.063c36.021,5.65,31.431-0.706,31.431-0.706c-4.237-8.122-32.843-19.069-33.196-20.128  c-0.353-1.06-15.891-7.063-15.891-7.063c-5.297-2.119-13.065-18.363-13.065-18.363c-5.649-6.003,22.247,4.238,22.247,4.238  c-2.119,1.766,10.947,8.828,10.947,8.828c30.724-1.766,49.439,17.303,49.439,17.303c19.068,29.31,19.422,14.832,19.422,14.832  c4.943-16.597-15.892-54.029-15.892-54.029c0.706-3.531,15.186,8.122,15.186,8.122c2.472-3.531,3.885,6.709,3.885,6.709  c0.353,4.237,7.063,18.362,7.063,18.362c4.942,22.954,11.3,9.888,11.3,9.888l8.122,16.597c2.472,4.591-8.122,18.01-8.122,18.01  c-0.354,4.944,1.06,4.59-8.828,18.009s-3.885,21.188-3.885,21.188c-2.473,11.653,13.064,10.947,13.064,10.947  c4.591,3.884,10.595,3.884,10.595,3.884c3.179,3.531,7.415,2.472,7.415,2.472c2.825-6.709,13.772-3.178,13.772-3.178  c2.472-4.238,16.95-4.944,16.95-4.944c1.766-4.591,2.472-7.416,8.475-8.475c6.004-1.06-37.432-76.982-37.432-76.982  c11.301-1.413-3.179-23.307-3.179-23.307c-3.885-11.653,16.244,14.125,20.128,16.597c3.886,2.472,5.65,6.356,2.825,6.003  s-6.003,3.532-3.531,3.885c2.473,0.354,25.427,26.837,31.43,44.847c6.003,18.01,16.597,25.072,27.544,35.666  c10.947,10.594,9.534,53.322,9.534,53.322c-0.706,15.538,9.888,34.253,9.888,34.253c3.531,6.709-3.885,38.844-3.885,38.844  c-3.531,3.884-1.06,5.297-1.06,5.297c1.767,2.119,13.771,25.425,13.771,25.425c-3.178-0.353,3.179,6.003,3.179,6.003  c9.181,10.594-2.119,5.297-2.119,5.297c-10.594-2.825,1.767,14.479,1.767,14.479c2.119,3.178-13.772-4.944-13.772-4.944  c-16.243-1.06,4.238,11.653,4.238,11.653c15.185,12.713-4.944,4.943-4.944,4.943c-8.122-3.179-2.472,8.828-2.472,8.828  c5.649,2.824,36.02,15.186,36.02,15.186c0.706,6.711-4.591,15.539-4.591,15.539c0.706,7.063-3.179,13.064-3.179,13.064  c-2.118,14.479-3.178,15.891-3.178,15.891c-7.416,0.354-20.481,24.721-20.481,24.721c-3.179,4.591-21.188,25.777-21.188,25.777  c-3.531,12.359-35.313-0.354-35.313-0.354c-11.653,6.003-8.122,0-8.122,0c-0.706-3.884,7.771-14.479,7.771-14.479  c12.358-4.59,7.769-23.658,7.769-23.658c7.063-2.473-12.713-7.416-12.359-9.534c0.354-2.119,10.595-4.591,10.595-4.591  c14.125-3.531,6.355-7.77,6.355-7.77c-1.06-7.063,4.237-16.95,4.237-16.95c20.48-1.413,0-30.019,0-30.019  c-19.068-13.418-20.835-23.659-20.835-23.659c22.247-14.478,7.77-36.372,8.122-42.729c0.354-6.356,2.473-44.494,2.473-44.494  c-3.531-10.947-8.828-34.96-8.828-34.96c3.885-9.181,16.949-31.428,16.949-31.428c4.944-7.416,20.481-15.891,16.598-21.188  c-3.885-5.297-17.655-2.119-17.655-2.119c-13.772-2.472-12.713,6.709-12.713,6.709c-2.825,1.766-4.237,10.594-4.237,10.594  c-1.273,14.007-16.95,25.072-16.95,25.072c-19.775,10.947-3.531,18.01-3.531,18.01c10.595,11.653-6.71,12.006-6.71,12.006  c-19.422-3.178-4.942,14.831-4.942,14.831c19.067,22.601,13.771,27.544,13.771,27.544c-18.009,1.766,4.237,18.009,4.237,18.009  s-1.412-3.531-1.06-0.353c0.354,3.178,5.649,10.594,7.063,14.125c1.412,3.531-5.65,3.885-5.65,3.885  c1.061,16.95-26.132,9.534-26.132,9.534s0,0-2.824,0.353c-2.824,0.354-22.601-1.059-32.841-4.944  c-10.241-3.884-22.248-3.884-22.248-3.884s-7.063,3.178-20.481,2.825s-27.544,4.59-27.544,4.59  c-7.771-0.706,7.415-8.475,7.769-8.122s10.24-9.535-3.885-8.475c-38.485,2.887-57.561-15.185-57.561-15.185  c-3.53-2.472-8.122-7.416-8.122-7.416c-17.655-3.531,2.473,21.894,2.473,21.894c2.119,2.472-0.354,4.238-0.354,4.238  c-1.413-2.825-15.185-12.359-15.185-12.359C368.316,357.817,365.91,355.461,361.794,351.072z'\n  }),\n  createElement('path', {\n    id: 'path466',\n    fill: '#4C0000',\n    d: 'M319.604,330.579c0,0,20.481,9.887,25.072,14.831c4.591,4.944,29.311,25.072,29.311,25.072  s-9.535-3.531-14.125-6.709c-4.592-3.178-23.66-17.656-23.66-17.656S329.492,335.522,319.604,330.579z'\n  }),\n  createElement('path', {\n    id: 'path470',\n    fill: '#99CC32',\n    d: 'M217.181,275.496c0.595-0.261-0.33-5.05-0.69-6.008c-1.804-4.813-17.656-7.416-17.656-7.416  c-0.401,2.41-0.498,5.229-0.311,8.121C198.523,270.192,207.119,279.936,217.181,275.496z'\n  }),\n  createElement('path', {\n    id: 'path474',\n    fill: '#659900',\n    d: 'M217.181,275.143c-0.793,0.279-0.026-4.827-0.337-5.655  c-1.804-4.813-18.009-7.592-18.009-7.592c-0.401,2.41-0.498,5.228-0.311,8.12C198.523,270.015,206.06,279.053,217.181,275.143z'\n  }),\n  createElement('path', {\n    id: 'path478',\n    d: 'M209.428,275.395c-1.104,0-1.997-2.013-1.997-4.495c0-2.481,0.894-4.494,1.997-4.494  c1.104,0,1.999,2.013,1.999,4.494C211.427,273.382,210.532,275.395,209.428,275.395z'\n  }),\n  createElement('path', {\n    id: 'path486',\n    d: 'M128.915,448.525c0,0-9.888,17.655,33.9,7.063c0,0,24.719-2.119,28.957-6.355  c2.119,1.411,16.89,6.591,21.894,7.769c12.006,2.825,26.838-14.833,26.838-14.833s8.122-18.539,13.066-18.539  c4.944,0-0.707,2.825-0.707,2.825s-11.653,17.834-10.947,20.659c0,0-9.181,35.313-37.432,36.726c0,0-28.515,1.678-26.131,12.007  c0,0,15.538-4.237,19.775,0c0,0,19.069-0.707,4.944,10.595l-12.006,20.48c0,0,0.247,6.918-17.656,0.706  c-17.303-6.003-35.489-28.78-35.489-28.78S109.758,473.156,128.915,448.525z'\n  }),\n  createElement('path', {\n    id: 'path490',\n    fill: '#E59999',\n    d: 'M126.796,455.588c0,0-3.531,16.95,61.444-1.413c0,0,7.769,0,12.007,1.413  c4.237,1.412,25.425,6.356,28.957,4.237c0,0-12.713,24.013-33.194,21.188c0,0-23.307,2.825-22.6,11.302  c0,0,7.063,12.712,15.538,16.949c0,0,4.944,4.237,4.237,9.888c-0.706,5.649-5.65,8.476-9.181,9.888  c-3.531,1.413-9.181-4.237-12.006-4.237s-17.656-11.3-25.425-19.774c-7.769-8.476-22.6-29.662-21.894-34.606  C125.384,465.476,126.796,455.588,126.796,455.588z'\n  }),\n  createElement('path', {\n    id: 'path494',\n    fill: '#B26565',\n    d: 'M132.446,486.398c4.591,6.974,10.241,14.39,14.125,18.627  c7.769,8.476,22.6,19.774,25.425,19.774c2.825,0,8.475,5.65,12.006,4.237c3.531-1.412,8.475-4.237,9.181-9.888  c0.707-5.649-4.237-9.888-4.237-9.888c-5.414-2.707-10.251-8.873-13.04-12.975c0,0,0.327,4.499-8.854,3.087  c-9.181-1.413-18.363-6.356-21.188-12.007c-2.825-5.65-7.063-9.888-4.238-3.531s7.063,12.713,9.888,13.419  c2.825,0.706,2.119,2.825-2.119,2.119c-4.238-0.707-9.182-1.413-16.95-10.594L132.446,486.398L132.446,486.398z'\n  }),\n  createElement('path', {\n    id: 'path498',\n    fill: '#992600',\n    d: 'M127.855,449.231c0,0,3.178-24.016,5.297-31.077c0,0-1.413-12.007,2.825-19.422  c4.237-7.417,7.769-18.363,13.066-27.897s5.65-16.597,12.712-19.422c7.062-2.825,17.656-18.01,22.6-19.775  c4.944-1.765,4.591-0.353,4.591-0.353s12.006-26.131,36.019-19.069c0,0-28.604-4.944-0.706-21.541c0,0-8.475,1.942-2.648-10.417  c3.886-8.242,3.001,3.708-16.421,24.542c0,0-8.828,15.185-18.009,20.481c-9.181,5.297-30.369,17.657-32.488,24.366  c-2.119,6.709-7.769,16.95-11.3,19.775c-3.531,2.825-8.475,10.241-9.181,16.244c0,0-2.119,7.063-4.591,9.181  c-2.472,2.119-2.825,7.769-2.825,11.299c0,3.532-3.531,8.477-3.178,12.714c0,0,1.412,33.549,0.706,37.079L127.855,449.231z'\n  }),\n  createElement('path', {\n    id: 'path502',\n    fill: '#FFFFFF',\n    d: 'M112.671,457.354c0,0-3.531-2.472-11.3,8.122c0,0,12.889,58.267,12.889,60.738  c0,0,1.942-3.708-0.354-16.421c-2.295-12.713-3.884-35.137-3.884-35.137L112.671,457.354z'\n  }),\n  createElement('path', {\n    id: 'path506',\n    fill: '#992600',\n    d: 'M150.809,350.354c0,0-31.076,5.65-30.369,57.207l-1.413,43.79c0,0-2.119-45.202-4.238-48.026  c-2.119-2.825,4.944-22.601-0.706-12.007c0,0-24.719,24.719-10.594,62.152c0,0,2.648,5.827-2.648-2.295  c0,0-8.122-22.249-6.18-33.549c0,0,0.353-3.885,3.708-8.828c0,0,15.185-20.659,19.952-24.72c0,0,3.178-25.425,30.369-34.606  C148.69,349.471,158.754,345.41,150.809,350.354z'\n  }),\n  createElement('path', {\n    id: 'path510',\n    d: 'M396.939,233.468c1.164-0.625,1.148-2.338,2.174-2.644c2.027-0.607,2.317-2.491,3.231-3.875  c1.542-2.329,1.883-5.036,2.91-7.668c0.48-1.236,0.527-2.922-0.024-4.087c-2.072-4.381-3.313-8.705-5.858-12.988  c-0.473-0.794-0.937-2.196-1.29-3.252c-0.817-2.443-3.037-4.193-4.556-6.524c-0.51-0.779,0.419-2.412-0.847-2.56  c-1.584-0.186-4.143-1.209-4.554,0.602c-1.038,4.568,0.747,9.022,2.456,13.334c-1.381,1.222-0.791,2.848-0.522,4.202  c1.255,6.367-0.86,12.286-2.204,18.419c-0.041,0.184,0.563,0.533,0.514,0.643c-2.158,4.743-4.722,9.06-7.935,13.264  c-1.338,1.751-2.878,3.369-3.755,5.246c-0.649,1.39-1.37,3.095-0.929,4.84c-6.065,4.908-10.038,11.697-14.647,18.488  c-0.815,1.201-0.303,3.335,0.672,3.811c1.435,0.703,3.123-1.105,3.953-2.599c0.687-1.232,1.31-2.38,2.177-3.516  c0.233-0.309-0.081-1.049,0.157-1.262c4.647-4.144,7.596-9.328,11.927-13.509c3.442-0.581,6.157-2.343,9.243-4.131  c0.544-0.316,1.469,0.124,1.98-0.221c3.095-2.078,3.091-5.673,3.278-9.045C394.58,236.872,394.927,234.547,396.939,233.468z'\n  }),\n  createElement('path', {\n    id: 'path514',\n    d: 'M381.329,225.583c0.22-0.136-0.055-0.883,0.138-1.264c0.286-0.572,0.998-0.904,1.284-1.476  c0.192-0.381-0.096-1.052,0.146-1.303c4.118-4.321,4.572-9.66,2.743-14.909c1.809-1.095,1.915-3.323,1.165-4.818  c-1.506-3.002-1.847-6.402-3.567-9.127c-1.416-2.24-4.202-4.437-6.623-2.136c-0.743,0.706-1.311,2.096-0.819,3.353  c0.113,0.288,0.616,0.545,0.568,0.69c-0.188,0.572-1.152,0.967-1.163,1.448c-0.053,2.641-1.737,5.309-0.625,7.656  c1.363,2.876,2.809,6.155,4.003,9.291c-2.179,3.736-0.355,8.06-3.45,11.374c-0.24,0.258-0.225,0.939-0.009,1.296  c0.516,0.858,1.231,1.575,2.09,2.091c0.357,0.213,0.972,0.217,1.324-0.002C379.553,227.106,380.256,226.247,381.329,225.583z'\n  }),\n  createElement('path', {\n    id: 'path518',\n    d: 'M492.233,207.377c2.451,3.164,2.964,8.099-0.653,10.554c0.971,5.842,6.888,2.348,10.594,1.412  c-0.191-0.685,0.208-1.292,0.708-1.301c1.866-0.026,3.066-1.849,4.941-1.523c0.767-2.75,3.659-3.989,4.796-6.425  c3.048-6.524,2.004-14.069-2.559-19.8c-0.356-0.449,0.025-1.361-0.192-2c-1.335-3.904-4.986-4.46-8.401-5.675  c-2.078-6.842-3.245-13.959-6.354-20.481c-2.851-0.441-4.082-3.512-6.443-4.783c-2.354-1.27-3.355,1.519-3.284,3.365  c0.014,0.362,0.812,0.757,0.512,1.402c-0.136,0.29-0.595,0.486-0.595,0.722c0.002,0.238,0.394,0.47,0.629,0.707  c-1.62,1.448-4.134,2.29-4.653,4.312c-1.686,6.55,2.857,12.068,5.804,17.72c1.044,2.004-0.256,4.249-1.598,6.381  c-0.773,1.227-0.583,3.217-0.097,4.729C486.714,200.806,489.521,203.876,492.233,207.377z'\n  }),\n  createElement('path', {\n    id: 'path522',\n    d: 'M426.622,239.84c-2.626,3.268-8.65,7.804-3.5,11.208c0.343,0.228,0.996,0.234,1.302-0.002  c3.568-2.763,7.104-4.357,11.405-5.385c0.22-0.051,0.703,0.773,1.354,0.489c2.849-1.242,6.397-1.139,8.487-3.501  c6.651,0.396,12.946-1.575,18.934-3.884c2.051-0.791,4.293-1.778,6.412-2.665c2.431-1.017,4.557-2.655,6.521-4.67  c0.233-0.24,0.858-0.082,1.331-0.082c-0.07-1.523,1.628-1.748,2.063-2.846c0.163-0.41-0.102-1.109,0.133-1.289  c3.775-2.878,5.399-6.441,3.336-10.638c-0.504-1.021-0.942-2.112-1.941-2.952c-1.916-1.608-3.862-0.101-5.711-0.637  c-0.28,1.108-1.567,0.805-2.249,1.155c-1.517,0.775-3.87-0.258-5.387,0.515c-2.405,1.227-4.598,1.526-7.106,2.191  c-0.552,0.145-1.925-0.025-2.208,1.083c-0.236-0.237-0.497-0.65-0.685-0.611c-3.369,0.699-5.595,1.077-7.892,4.064  c-0.182,0.235-0.962-0.081-1.243,0.157c-1.688,1.427-2.403,3.605-4.349,4.792c-0.354,0.217-0.977-0.079-1.319,0.148  c-1.141,0.761-1.787,1.893-2.922,2.682c-0.581,0.404-1.287-0.169-1.229-0.622c0.433-3.438,1.585-6.593,0.569-9.905  c3.667-4.449,8.111-7.891,11.301-12.713c0.025-3.824,1.248-7.613,1.049-11.28c-0.019-0.341-0.526-1.635-0.748-2.248  c-0.552-1.508,1.049-3.39-0.441-4.668c-2.479-2.124-4.761-0.578-6.216,1.953c-3.245,0.688-6.893,1.912-9.679-0.267  c-1.778-1.39-2.799-2.989-4.21-4.854c-1.738-2.299-1.147-4.834-1.023-7.596c0.011-0.226-0.546-0.466-0.546-0.703  c0.002-0.238,0.391-0.47,0.627-0.706c-1.246-1.105-1.731-2.974-3.531-3.532c0.538-1.928-0.654-3.489-2.192-4.022  c-3.522-1.22-6.483,2.156-9.823,2.285c-0.908,0.034-1.732-1.799-2.878-2.373c-0.764-0.381-2.006-0.439-2.646,0.03  c-1.215,0.89-2.255,1.091-3.593,1.453c-2.854,0.77-5.11,2.701-7.725,4.211c-2.622,1.513-4.31,4.05-6.216,6.381  c-1.661,2.034-1.901,6.296,0.605,7.179c3.254,1.148,5.557-3.625,9.027-3.049c0.551,0.09,0.915,0.639,0.721,1.324  c0.688,0.193,1.071-0.212,1.412-0.706c1.515,1.799,3.57,2.394,5.227,3.936c1.714,1.596,4.796,0.858,6.589,2.619  c2.698,2.652,1.712,7.386,5.136,9.69c-1.034,2.318-2.106,4.573-2.698,7.092c-0.497,2.129,1.258,4.243,3.396,4.082  c2.222-0.166,2.684-1.506,3.54-3.406c0.472,0.472,1.3,0.996,1.228,1.377c-0.807,4.214-2.62,7.733-3.429,12.025  c-0.104,0.56-0.644,0.917-1.33,0.722c-0.826,7.326-7.98,11.553-12.475,17.141c-0.712,0.886-0.719,3.092,0.004,3.803  c2.478,2.449,5.938-0.281,8.938-1.169c0.376-2.129,1.893-3.792,4.245-3.694c0.452,0.018,0.866-0.939,1.438-1.169  c0.614-0.244,1.501,0.152,2.007-0.198c3.053-2.11,5.539-4.063,8.606-6.162c0.339-0.231,0.946,0.05,1.328-0.141  c0.574-0.286,0.904-0.969,1.475-1.296c0.614-0.353,1.041,0.159,1.383,0.653c-1.142,0.616-1.147,2.306-2.176,2.663  c-1.367,0.473-2.358,1.379-3.549,2.168c-0.516,0.341-1.68-0.097-1.862,0.219C429.966,237.508,427.875,238.281,426.622,239.84z'\n  }),\n  createElement('path', {\n    id: 'path526',\n    d: 'M328.785,152.602c0,0-16.312-5.071-36.019,40.257c0,0-4.238,9.181-8.475,12.712  c-4.238,3.531-24.013,9.888-27.544,16.95l-18.363,28.25c0,0,26.131-28.25,31.782-32.488c0,0,14.125-14.832,8.475-2.825  c0,0-24.719,19.069-22.601,35.313c0,0-9.887,25.425-11.3,28.957c0,0,28.25-56.5,32.488-58.62c4.237-2.119,6.356-2.119,4.237,4.238  c-2.119,6.357-2.825,35.313-7.769,38.844c0,0,14.125-36.02,12.712-41.669c0,0,5.65-6.356,9.888,2.825l-2.119,28.25l7.769,21.188  c0,0-4.237-19.775-1.413-47.319c0,0-3.531-18.363,3.531-8.475c7.062,9.888,24.013,20.481,24.013,28.957  c0,0-9.181-31.075-25.425-39.55l-7.063,10.594l-2.119-3.531c0,0-6.356-1.413,1.413-13.419c7.769-12.006,7.063-13.419,7.063-13.419  s11.3,12.713,14.125,12.713c0,0,23.307-13.419,25.425,29.663c0,0,12.007-25.425-4.237-37.432c0,0-26.132-3.531-24.013-12.712  l12.713-21.894c6.356-9.182,3.531-4.238,3.531-4.238L328.785,152.602z'\n  }),\n  createElement('path', {\n    id: 'path530',\n    d: 'M293.473,181.558c0,0-22.6,0-28.25,9.181l-12.713,16.95c0,0,30.369-17.656,37.432-19.775  S293.473,181.558,293.473,181.558z'\n  }),\n  createElement('path', {\n    id: 'path534',\n    d: 'M222.847,192.858c0,0-3.531,2.119-4.238,7.063c-0.706,4.944-4.944,5.65-3.531,10.594  c1.413,4.944,4.944,9.182,4.944,2.119c0-7.063,2.825-10.594,4.238-12.712C225.672,197.802,228.497,190.033,222.847,192.858z'\n  }),\n  createElement('path', {\n    id: 'path538',\n    d: 'M207.31,300.916c0,0-14.832-7.063-20.481-13.419c-5.65-6.356-4.852,2.765-13.419,2.119  c-10.324-0.779-8.475-28.957-8.475-28.957l-7.063,13.418c0,0-2.119,25.425,12.006,21.188c6.898-2.069,9.181,0.706,6.356,2.119  c-2.825,1.413,9.887,2.119,4.943,4.944c-4.943,2.825,20.481-6.356,16.244,12.006L207.31,300.916z'\n  }),\n  createElement('path', {\n    id: 'path542',\n    d: 'M185.063,326.341c0,0-27.191,7.769-33.547-9.181c0,0-8.475,4.237-4.591,9.534  c3.885,5.297,6.003,6.003,6.003,6.003s9.534,2.119,8.475,3.531c-1.06,1.413-5.297,7.416-5.297,7.416S174.115,333.05,185.063,326.341  z'\n  }),\n  createElement('path', {\n    id: 'path546',\n    fill: '#FFFFFF',\n    d: 'M588.337,464.416c-0.754,3.768-3.704,5.182-7.063,6.355c-3.386-1.69-7.973-7.176-11.301-3.53  c-0.837-0.849-2.213-0.954-2.819-2.123c-0.82-1.585-0.342-3.433-0.944-4.841c-0.962-2.246-2.214-4.658-1.886-7.161  c3.188-1.258,4.239-4.623,3.401-7.735c-0.122-0.454-0.879-0.802-0.525-1.418c0.329-0.57,0.89-0.972,1.36-1.441  c-0.237,0.237-0.493,0.648-0.689,0.613c-1.077-0.188-0.857-1.313-0.628-1.995c1.032-3.083,4.589-3.549,6.969-1.443  c0.452-0.998,1.352-0.655,2.118-0.706c-0.088-1.022,0.633-1.953,0.982-2.694c0.913-1.938,3.791,0.014,5.197-1.065  c1.899-1.457,3.776-2.691,5.681-1.628c3.193,1.789,6.212,3.93,8.327,7.004c1.017,1.473,1.439,3.733,1.338,5.426  c-0.067,1.143-2.507,0.521-3.111,2.161c-1.139,3.086,2.095,4.003,3.43,6.364c0.35,0.616-0.117,1.153-0.673,1.326  c-0.726,0.227-2.11-0.107-1.866,0.691C597.351,462.212,592.484,463.409,588.337,464.416z'\n  }),\n  createElement('path', {\n    id: 'path550',\n    fill: '#FFFFFF',\n    d: 'M571.385,499.022c-0.012-3.068-2.839-6.17-0.704-9.183c0.238,0.237,0.471,0.627,0.706,0.627  c0.238,0,0.471-0.39,0.706-0.627c2.641,3.913,9.088,5.552,8.837,10.576c-0.038,0.79-1.958,2.41-0.36,3.55  c-3.201,2.38-3.3,6.564-4.944,9.887c-2.186-0.505-4.325-1.146-6.356-2.117c0.622-2.624,0.415-5.599,1.863-7.929  C571.896,502.575,571.391,500.67,571.385,499.022z'\n  }),\n  createElement('path', {\n    id: 'path554',\n    fill: '#CCCCCC',\n    d: 'M277.935,483.132c0,0-29.765,17.896-4.944-9.182c15.538-16.95,33.194-26.838,33.194-26.838  s18.362-7.771,24.719-9.89c6.355-2.119,33.193-11.301,38.845-12.007c5.649-0.706,22.6-7.769,34.606-0.706  c12.006,7.063,26.131,14.831,26.131,14.831s-28.956-14.831-35.313-10.594c-6.356,4.237-19.069,3.531-29.663,9.182  c0,0-26.131,7.771-31.781,11.303c-5.649,3.53-24.013,24.013-26.837,22.601c-2.825-1.413,0.706-2.119,2.825-7.063  c2.119-4.943-1.412-7.77-15.538,3.531C280.054,479.601,277.935,483.132,277.935,483.132z'\n  }),\n  createElement('path', {\n    id: 'path558',\n    d: 'M291.01,472.596c0,0,2.49-23.022,17.459-20.084c0,0,14.523-7.361,19.33-10.837c0,0,14.37-3.006,16.685-4.095  c32.627-15.361,58.614-7.383,59.581-9.359c0.965-1.977,35.614,10.59,41.986,17.806c0.69,0.781-18.063-9.884-35.188-13.223  c-14.607-2.85-52.748,0.438-72.005,10.211c-5.249,2.664-21.043,12.877-25.513,12.682C308.878,455.498,291.01,472.596,291.01,472.596  z'\n  }),\n  createElement('path', {\n    id: 'path562',\n    fill: '#CCCCCC',\n    d: 'M284.292,517.738c0,0-26.838-4.237,2.825-7.063c0,0,31.782-3.531,38.844-12.713  c0,0,24.013-16.244,28.956-16.95c4.944-0.706,57.913-13.419,58.619-17.656c0.707-4.236,10.595-4.236,13.419-2.824  c2.825,1.413,1.413,3.53-3.531,4.943c-4.943,1.412-60.031,30.369-71.332,32.487c-11.3,2.119-31.781,15.538-40.256,17.656  C303.36,517.738,284.292,517.738,284.292,517.738z'\n  }),\n  createElement('path', {\n    id: 'path566',\n    d: 'M318.757,504.676c0,0-15.153-1.464,0.033-2.909c0,0,15.566-6.046,19.183-10.748c0,0,12.296-8.316,14.826-8.678  c2.531-0.362,27.18-6.872,27.542-9.04c0.362-2.17,60.51-24.384,68.314-18.751c5.14,3.709-12.343,0.748-29.354,8.535  c-2.393,1.095-62.164,26.85-67.95,27.934c-5.785,1.087-16.271,7.956-20.611,9.04C326.402,501.145,318.757,504.676,318.757,504.676z'\n  }),\n  createElement('path', { id: 'path570', d: 'M304.773,508.557c0,0,9.181-0.706,7.063,2.119c-2.119,2.825-6.357,1.412-6.357,1.412L304.773,508.557z' }),\n  createElement('path', { id: 'path574', d: 'M292.061,511.382c0,0,9.181-0.706,7.063,2.119c-2.119,2.825-6.356,1.412-6.356,1.412L292.061,511.382z' }),\n  createElement('path', { id: 'path578', d: 'M273.698,514.207c0,0,9.181-0.706,7.063,2.119c-2.119,2.824-6.356,1.412-6.356,1.412L273.698,514.207z' }),\n  createElement('path', { id: 'path582', d: 'M260.279,515.619c0,0,9.181-0.706,7.063,2.119c-2.118,2.825-6.356,1.412-6.356,1.412L260.279,515.619z' }),\n  createElement('path', { id: 'path586', d: 'M328.079,445.7c0,0,7.77,0,5.649,2.825c-2.119,2.824-7.769,2.117-7.769,2.117L328.079,445.7z' }),\n  createElement('path', { id: 'path590', d: 'M310.423,455.588c0,0,11.487-3.78,7.063,2.118c-2.118,2.825-6.356,1.413-6.356,1.413L310.423,455.588z' }),\n  createElement('path', { id: 'path594', d: 'M290.648,464.063c0,0,9.181-0.705,7.063,2.119c-2.118,2.825-6.356,1.412-6.356,1.412L290.648,464.063z' }),\n  createElement('path', { id: 'path598', d: 'M277.229,474.656c0,0,9.181-0.706,7.063,2.119c-2.118,2.824-6.356,1.411-6.356,1.411L277.229,474.656z' }),\n  createElement('path', { id: 'path602', d: 'M265.223,483.132c0,0,9.181-0.706,7.063,2.118c-2.119,2.825-6.356,1.413-6.356,1.413L265.223,483.132z' }),\n  createElement('path', { id: 'path606', d: 'M334.228,494.427c0,0,12.221-0.938,9.4,2.819c-2.82,3.761-8.461,1.881-8.461,1.881L334.228,494.427z' }),\n  createElement('path', { id: 'path610', d: 'M352.59,485.951c0,0,12.221-0.939,9.4,2.82c-2.819,3.761-8.461,1.88-8.461,1.88L352.59,485.951z' }),\n  createElement('path', { id: 'path614', d: 'M371.659,478.183c0,0,12.22-0.938,9.399,2.819c-2.819,3.761-8.461,1.881-8.461,1.881L371.659,478.183z' }),\n  createElement('path', { id: 'path618', d: 'M390.021,469.708c0,0,12.221-0.939,9.399,2.819c-2.819,3.761-8.461,1.88-8.461,1.88L390.021,469.708z' }),\n  createElement('path', { id: 'path622', d: 'M341.29,437.926c0,0,12.22-0.938,9.4,2.82c-2.82,3.761-9.874,3.293-9.874,3.293L341.29,437.926z' }),\n  createElement('path', { id: 'path626', d: 'M358.946,432.276c0,0,12.22-0.939,9.399,2.818c-2.818,3.762-10.58,3.293-10.58,3.293L358.946,432.276z' }),\n  createElement('path', { id: 'path630', d: 'M318.898,502.907c0,0,9.181-0.706,7.063,2.118c-2.119,2.824-6.355,1.413-6.355,1.413L318.898,502.907z' }),\n  createElement('path', {\n    id: 'path634',\n    fill: '#992600',\n    d: 'M189.653,327.753c0,0-7.769,15.538-8.475,21.188c0,0,1.413-15.538,3.531-19.069  C186.828,326.341,189.653,327.753,189.653,327.753z'\n  }),\n  createElement('path', {\n    id: 'path638',\n    fill: '#992600',\n    d: 'M157.165,352.472c0,0-5.65,25.425-4.944,30.369c0,0-2.119-20.481-1.412-22.6  C151.515,358.123,157.165,352.472,157.165,352.472z'\n  }),\n  createElement('path', {\n    id: 'path642',\n    fill: '#CCCCCC',\n    d: 'M193.891,220.755l-0.353,5.65l-3.885,0.354c0,0,25.072,22.247,26.132,35.666  C215.785,262.425,217.197,247.946,193.891,220.755z'\n  }),\n  createElement('path', {\n    id: 'path646',\n    d: 'M200.925,222.989c-0.761-0.734-0.374-2.05-1.095-2.509c-1.428-0.911,2.292-1.012,1.889-2.276  c-0.676-2.129-0.346-2.167-0.562-4.419c-0.101-1.056,0.938-3.775,1.618-4.552c2.553-2.917,0.215-8.094,3.111-10.833  c0.537-0.51,1.201-1.485,1.704-2.223c1.164-1.7,3.254-2.562,4.931-4.024c0.562-0.487,0.207-1.948,1.211-1.785  c1.261,0.203,3.452-0.026,3.373,1.458c-0.2,3.743-2.546,6.78-4.806,9.725c0.796,1.243-0.013,2.364-0.514,3.348  c-2.357,4.626-2.023,9.642-2.331,14.657c-0.009,0.15-0.551,0.288-0.537,0.381c0.623,4.123,1.654,8.005,3.207,11.941  c0.646,1.642,1.478,3.222,1.743,4.859c0.196,1.211,0.378,2.682-0.343,3.927c3.593,5.103,1.282,9.783,3.346,16.018  c0.365,1.104,3.353,4.483,2.535,4.199c-4.437-1.538-4.635-2.241-4.947-3.57c-0.258-1.1-0.84-3.531-1.259-4.594  c-0.113-0.29-0.415-3.616-0.553-3.832c-2.671-4.206-0.274-3.895-2.692-8.059c-2.521-1.201-4.227-3.15-6.21-5.202  c-0.35-0.36,1.668-1.638,1.349-2.014c-1.928-2.276-3.964-3.63-3.371-6.267C201.997,226.126,202.238,224.26,200.925,222.989z'\n  }),\n  createElement('path', {\n    id: 'path650',\n    d: 'M194.597,226.052c0,0,0.707,12.006,4.944,14.832c4.238,2.825,2.119,1.413-3.531-0.706  c-5.65-2.119-3.531-3.531-3.531-3.531s-4.944,0.706-0.706,4.237c4.237,3.531,10.594,7.769,7.769,7.769s-16.244-7.063-16.244-12.006  c0-4.944-1.766-12.183-1.766-12.183s1.942-1.413,10.417-1.236C191.948,223.228,194.42,224.463,194.597,226.052z'\n  }),\n  createElement('path', {\n    id: 'path654',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M193.184,258.894c0,0-15.043-4.928-47.672,1.059  c0,0,15.946-3.669,49.085,0.353C212.783,262.513,193.184,258.894,193.184,258.894z'\n  }),\n  createElement('path', {\n    id: 'path658',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M196.889,258.768c0,0-14.56-6.211-47.586-3.067  c0,0,16.205-2.276,48.871,4.596C216.103,264.068,196.889,258.768,196.889,258.768z'\n  }),\n  createElement('path', {\n    id: 'path662',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M200.045,258.932c0,0-14.058-7.276-47.226-6.596  c0,0,16.329-1.066,48.395,8.217C218.811,265.647,200.045,258.932,200.045,258.932z'\n  }),\n  createElement('path', {\n    id: 'path666',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M202.288,259.326c0,0-12.049-7.604-41.842-9.543  c0,0,14.724,0.3,42.764,11.086C218.599,266.789,202.288,259.326,202.288,259.326z'\n  }),\n  createElement('path', {\n    id: 'path670',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M405.838,277.894c0,0-1.642,1.137-1.264-0.948  c0.38-2.085,50.185-25.339,56.564-24.897C461.14,252.048,407.732,275.365,405.838,277.894z'\n  }),\n  createElement('path', {\n    id: 'path674',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M399.846,279.021c0,0-1.547,1.263-1.333-0.846  c0.214-2.108,48.04-29.202,54.436-29.262C452.947,248.914,401.537,276.354,399.846,279.021z'\n  }),\n  createElement('path', {\n    id: 'path678',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M394.044,281.449c0,0-1.462,1.363-1.388-0.755  c0.074-2.117,35.063-29.479,52.389-32.788C445.045,247.906,413.21,262.255,394.044,281.449z'\n  }),\n  createElement('path', {\n    id: 'path682',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M388.966,284.739c0,0-1.314,1.226-1.248-0.68  c0.066-1.907,31.557-26.532,47.147-29.509C434.865,254.55,406.216,267.464,388.966,284.739z'\n  }),\n  createElement('path', {\n    id: 'path686',\n    fill: '#CCCCCC',\n    d: 'M333.023,545.988c0,0-26.838-4.237,2.824-7.063c0,0,31.781-3.531,38.845-12.712  c0,0,24.013-16.244,28.956-16.95c4.943-0.707,33.899-7.063,34.606-11.301c0.706-4.237,11.3-8.475,14.125-7.063  c2.825,1.413,2.825,17.655-2.119,19.068c-4.942,1.412-38.138,14.125-49.438,16.244c-11.301,2.118-31.782,15.537-40.257,17.656  C352.092,545.988,333.023,545.988,333.023,545.988z'\n  }),\n  createElement('path', {\n    id: 'path690',\n    d: 'M461.915,479.953c0,0-5.297,2.825-7.416,7.416c0,0-11.3,18.716-36.372,24.366c0,0-40.609,15.891-54.382,19.422  c0,0-23.659,8.828-36.727,7.416c0,0-12.358,0.353-1.411,3.178c0,0,35.666-3.531,41.669-6.709c0,0,27.544-9.182,32.841-13.772  c5.297-4.59,37.432-13.419,41.315-16.949C445.317,500.789,462.621,485.957,461.915,479.953z'\n  }),\n  createElement('path', { id: 'path694', d: 'M358.24,535.589c0,0,9.231-0.398,7.195,2.336c-2.034,2.737-6.356,1.193-6.356,1.193L358.24,535.589z' }),\n  createElement('path', { id: 'path698', d: 'M345.523,537.977c0,0,9.23-0.398,7.196,2.336c-2.036,2.736-6.357,1.195-6.357,1.195L345.523,537.977z' }),\n  createElement('path', { id: 'path702', d: 'M327.11,540.18c0,0,9.231-0.399,7.195,2.336c-2.034,2.735-6.356,1.193-6.356,1.193L327.11,540.18z' }),\n  createElement('path', { id: 'path706', d: 'M313.631,541.141c0,0,9.232-0.398,7.197,2.336c-2.036,2.736-6.358,1.193-6.358,1.193L313.631,541.141z' }),\n  createElement('path', { id: 'path710', d: 'M387.432,522.526c0,0,12.289-0.531,9.578,3.108c-2.708,3.642-8.463,1.59-8.463,1.59L387.432,522.526z' }),\n  createElement('path', { id: 'path714', d: 'M405.645,514.714c0,0,10.521-5.828,9.578,3.109c-0.477,4.513-8.463,1.589-8.463,1.589L405.645,514.714z' }),\n  createElement('path', { id: 'path718', d: 'M421.768,509.745c0,0,12.642-6.534,9.579,3.108c-1.374,4.326-8.465,1.59-8.465,1.59L421.768,509.745z' }),\n  createElement('path', { id: 'path722', d: 'M438.566,501.226c0,0,7.695-8.652,9.578,3.109c0.717,4.481-8.464,1.59-8.464,1.59L438.566,501.226z' }),\n  createElement('path', { id: 'path726', d: 'M372.28,530.444c0,0,9.23-0.401,7.196,2.336c-2.035,2.733-6.359,1.192-6.359,1.192L372.28,530.444z' }),\n  createElement('path', {\n    id: 'path730',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M435.138,316.105c0,0-1.282,1.174-1.284-0.717  c0-1.889,30.871-25.309,46.484-27.752C480.338,287.636,451.913,299.517,435.138,316.105z'\n  }),\n  createElement('path', {\n    id: 'path734',\n    d: 'M440.374,428.748c0,0,38.847,39.553,55.09,45.908c0,0,16.244,19.774,9.183,65.683  c0,0-5.65,13.419-11.301-23.307c0,0,5.649-44.494-14.125-16.244c0,0-14.834-17.479-3.533-16.95c0,0,5.651,3.531,6.357,0.706  c0.707-2.825-13.42-26.838-43.789-52.265C407.887,406.854,440.374,428.748,440.374,428.748z'\n  }),\n  createElement('path', {\n    id: 'path738',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M337.261,497.257c0,0-0.354-3.178,2.825-1.766  c3.178,1.412,169.503,12.358,225.298,54.734C565.384,550.227,485.576,509.264,337.261,497.257z'\n  }),\n  createElement('path', {\n    id: 'path742',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M355.623,489.488c0,0-0.354-3.18,2.825-1.767  c3.179,1.412,244.367-0.354,286.036,56.854C644.484,544.576,605.641,500.082,355.623,489.488z'\n  }),\n  createElement('path', {\n    id: 'path746',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M376.104,482.426c0,0-0.353-3.179,2.825-1.766  c3.18,1.412,309.343-21.541,351.013,35.666C729.941,516.326,712.991,471.125,376.104,482.426z'\n  }),\n  createElement('path', {\n    id: 'path750',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M393.762,473.95c0,0-0.354-3.178,2.824-1.767  c3.179,1.413,218.941-66.742,260.611-9.533C657.197,462.65,633.537,419.214,393.762,473.95z'\n  }),\n  createElement('path', {\n    id: 'path754',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M291.354,514.207c0,0-0.353-3.178,2.825-1.766  c3.178,1.412,34.606,5.297,38.138,73.804C332.317,586.245,319.604,512.088,291.354,514.207z'\n  }),\n  createElement('path', {\n    id: 'path758',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M275.816,517.032c0,0-0.353-3.18,2.825-1.767  c3.178,1.412,28.25-6.71,23.306,61.797C301.948,577.063,304.066,514.913,275.816,517.032z'\n  }),\n  createElement('path', {\n    id: 'path762',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M261.691,517.738c0,0-0.354-3.179,2.825-1.767  c3.179,1.412,30.369,2.473,8.475,42.022C272.991,557.995,289.941,515.619,261.691,517.738z'\n  }),\n  createElement('path', {\n    id: 'path766',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M345.252,439.457c0,0-0.784,3.529,1.951,1.381  c28.37-22.292,85.65-126.292,183.971-136.239C531.174,304.599,463.536,283.217,345.252,439.457z'\n  }),\n  createElement('path', {\n    id: 'path770',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M365.027,436.278c0,0-2.406-2.106,0.892-3.21  c3.298-1.104,201.831-129.115,271.194-115.05C637.113,318.018,589.252,304.758,365.027,436.278z'\n  }),\n  createElement('path', {\n    id: 'path774',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M328.229,447.053c0,0-0.897,2.823,2.122,1.101  c15.848-9.04,22.229-110.054,99.171-112.271C429.521,335.882,372.297,309.903,328.229,447.053z'\n  }),\n  createElement('path', {\n    id: 'path778',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M293.053,466.521c0,0-1.902,2.271,1.546,1.821  c18.091-2.352,55.884-75.222,134.348-66.254C428.947,402.089,372.507,376.759,293.053,466.521z'\n  }),\n  createElement('path', {\n    id: 'path782',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M312.895,455.704c0,0-1.432,2.594,1.868,1.49  c17.303-5.78,40.403-84.549,119.13-90.813C433.893,366.382,373.639,352.357,312.895,455.704z'\n  }),\n  createElement('path', {\n    id: 'path786',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M280.623,475.559c0,0-1.542,1.841,1.252,1.478  c14.653-1.905,45.265-60.929,108.822-53.665C390.696,423.37,344.979,402.854,280.623,475.559z'\n  }),\n  createElement('path', {\n    id: 'path790',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M267.206,485.992c0,0-1.775,1.845,1.035,1.637  c7.359-0.546,61.455-58.951,94.063-31.58C362.303,456.049,341.089,422.99,267.206,485.992z'\n  }),\n  createElement('path', {\n    id: 'path794',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M389.974,429.627c0,0-2.12-2.392,1.291-3.071  c3.411-0.679,216.529-102.579,283.56-79.862C674.823,346.693,629.021,327.494,389.974,429.627z'\n  }),\n  createElement('path', {\n    id: 'path798',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M330.904,543.164c0,0-0.354-3.179,2.824-1.768  c3.179,1.413,30.369,2.474,8.476,42.022C342.204,583.42,359.154,541.045,330.904,543.164z'\n  }),\n  createElement('path', {\n    id: 'path802',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M349.268,540.339c0,0-0.354-3.179,2.824-1.766  c3.18,1.412,34.607,5.297,38.14,73.804C390.23,612.377,377.518,538.22,349.268,540.339z'\n  }),\n  createElement('path', {\n    id: 'path806',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M361.273,537.514c0,0-0.354-3.179,2.824-1.766  c3.179,1.412,46.613,7.416,88.282,64.622C452.381,600.37,389.523,535.395,361.273,537.514z'\n  }),\n  createElement('path', {\n    id: 'path810',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M374.736,533.931c0,0-0.771-3.104,2.564-2.125  c3.337,0.979,39.416-2.375,106.684,57.969C483.984,589.773,402.455,528.076,374.736,533.931z'\n  }),\n  createElement('path', {\n    id: 'path814',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M393.1,526.162c0,0-0.771-3.104,2.565-2.126  c3.337,0.979,64.841,8.926,156.119,70.681C551.784,594.717,420.818,520.308,393.1,526.162z'\n  }),\n  createElement('path', {\n    id: 'path818',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M321.723,505.732c0,0-0.353-3.18,2.825-1.767  c3.179,1.412,97.464,6.003,151.14,53.322C475.688,557.289,414.064,513.545,321.723,505.732z'\n  }),\n  createElement('path', {\n    id: 'path822',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M304.066,512.795c0,0-0.353-3.179,2.825-1.766  c3.179,1.412,46.613,7.415,88.282,64.622C395.174,575.651,332.317,510.676,304.066,512.795z'\n  }),\n  createElement('path', {\n    id: 'path826',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M412.306,518.021c0,0-0.997-3.037,2.403-2.308  s65.321,4.147,160.88,59.049C575.589,574.764,438.462,514.036,412.306,518.021z'\n  }),\n  createElement('path', {\n    id: 'path830',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M427.138,513.785c0,0-0.998-3.039,2.402-2.309  c3.401,0.729,65.322,4.147,160.88,59.049C590.42,570.525,454.354,509.092,427.138,513.785z'\n  }),\n  createElement('path', {\n    id: 'path834',\n    fill: '#FFFFFF',\n    stroke: '#000000',\n    'stroke-width': '0.1',\n    d: 'M444.088,504.957c0,0-0.998-3.039,2.402-2.308  c3.399,0.729,79.447,8.385,237.863,68.936C684.354,571.585,471.303,500.264,444.088,504.957z'\n  }),\n  createElement('path', { id: 'path838', d: 'M247.566,517.032c0,0,9.182-0.706,7.063,2.118s-6.356,1.412-6.356,1.412L247.566,517.032z' }),\n  createElement('path', { id: 'path842', d: 'M301.948,541.751c0,0,9.181-0.706,7.063,2.119c-2.119,2.825-6.356,1.412-6.356,1.412L301.948,541.751z' }),\n  createElement('path', { id: 'path846', d: 'M286.41,541.045c0,0,9.182-0.706,7.063,2.119c-2.119,2.824-6.356,1.412-6.356,1.412L286.41,541.045z' }),\n  createElement('path', { id: 'path850', d: 'M118.022,520.177c0,0,8.908,2.336,5.98,4.313c-2.926,1.978-6.469-0.745-6.469-0.745L118.022,520.177z' }),\n  createElement('path', { id: 'path854', d: 'M121.554,503.227c0,0,8.908,2.336,5.98,4.313c-2.926,1.978-6.469-0.745-6.469-0.745L121.554,503.227z' }),\n  createElement('path', { id: 'path858', d: 'M108.841,495.458c0,0,8.908,2.336,5.98,4.312c-2.925,1.979-6.469-0.744-6.469-0.744L108.841,495.458z' }),\n  createElement('path', {\n    id: 'path862',\n    fill: '#CCCCCC',\n    d: 'M249.685,627.914c0,0-2.825,0-9.888,3.531c-3.531,0-23.307,6.355-33.194,24.013  C206.603,655.458,228.497,638.508,249.685,627.914z'\n  }),\n  createElement('path', {\n    id: 'path866',\n    fill: '#CCCCCC',\n    d: 'M404.56,791.494c0.249,0.456,0.348,1.197,0.862,1.228c1.161,0.07,3.339,0.603,3.118-0.521  c-1.497-7.604-3.041-16.319-10.338-19.51c-1.129-0.493-3.675,0.235-3.806,1.797c-0.225,2.69-0.432,5.072,0.114,7.661  c0.529,2.509,4.34,2.525,5.959,0.083C402.123,785.184,402.886,788.438,404.56,791.494z'\n  }),\n  createElement('path', {\n    id: 'path870',\n    fill: '#CCCCCC',\n    d: 'M385,799.854c1.321,2.494,1.097,5.776,3.595,6.771c1.308,0.519,4.573-1.202,3.835-3.099  c-1.416-3.64-2.101-7.594-4.554-10.79c-0.353-0.463,0.071-1.403-0.212-1.982c-1.048-2.154-3.07-3.452-5.556-2.871  c-1.97,3.891,0.058,7.648,2.744,10.666C385.094,798.816,384.801,799.48,385,799.854z'\n  }),\n  createElement('path', {\n    id: 'path874',\n    fill: '#CCCCCC',\n    d: 'M315.077,790.689c-0.19-0.666-0.258-1.483,0.033-2.052c0.938-1.822,2.338-3.805,1.742-5.608  c-0.613-1.864-2.585-1.543-3.731-0.538c-2.004,1.755-2.091,4.979-3.312,7.379c-0.347,0.682-0.256,1.692-1.034,2.383  c-0.838,0.744-1.613,3.435-1.444,4.442c0.094,0.553-0.229,18.047,0.163,17.583c1.093-1.295,6.478-18.481,6.6-20.058  C314.194,792.932,315.487,792.11,315.077,790.689z'\n  }),\n  createElement('path', {\n    id: 'path878',\n    fill: '#CCCCCC',\n    d: 'M269.81,778.697c4.651-4.413,9.577-9.642,8.796-16.195c-0.205-1.723-3.339-0.792-3.669,0.701  c-1.416,6.4-5.016,11.099-9.55,15.322c-3.877,3.613-7.165,14.814-7.58,15.713C264.334,784.958,268.319,780.109,269.81,778.697z'\n  }),\n  createElement('path', {\n    id: 'path882',\n    fill: '#CCCCCC',\n    d: 'M245.843,768.167c0.923-0.653,0.39-1.521,0.773-2.106c1.683-2.574,3.979-4.773,4.012-7.844  c0.005-0.489-0.662-1.034-1.254-0.639c-0.489,0.324-1.093,0.555-1.284,0.784c-3.584,4.322-6.056,9.04-8.604,14.005  c-0.323,0.63-2.343,8.56-1.79,8.756c0.422,0.148,3.459-7.232,3.83-7.434C243.756,772.479,243.777,769.627,245.843,768.167z'\n  }),\n  createElement('path', {\n    id: 'path886',\n    fill: '#CCCCCC',\n    d: 'M275.387,802.674c0.784-1.534,3.567-3.656,3.367-5.226c-0.208-1.64,0.618-4.188-0.992-2.973  c-2.22,1.675-8.309,4.057-8.786,14.312C268.93,809.795,274.182,805.04,275.387,802.674z'\n  }),\n  createElement('path', {\n    id: 'path890',\n    fill: '#CCCCCC',\n    d: 'M300.889,772.344c0.706-1.179,1.956-0.344,2.767-0.809c1.144-0.656,2.223-1.643,2.738-2.788  c1.713-3.794,4.836-7.008,5.089-11.234c-2.634-2.479-3.831,1.121-4.944,2.825c-2.336-2.908-4.1,0.4-6.395,1.316  c-0.124,0.05-0.5-0.563-0.632-0.516c-2.078,0.776-3.279,2.687-5.041,4.064c-0.302,0.236-1.017-0.082-1.276,0.158  c-1.151,1.064-2.869,1.639-3.364,2.843c-1.959,4.78-7.504,8.479-10.835,21.795c0.672,1.604,7.966-11.728,8.826-12.959  c1.476-2.112,1.685,2.933,3.938,1.757c0.09-0.048,0.418,0.372,0.655,0.608c0.342-0.494,0.727-0.898,1.413-0.706  c0-0.706-0.237-1.688,0.118-1.969c2.184-1.726,2.036-3.61,3.413-5.801C298.166,772.324,300.039,771.055,300.889,772.344z'\n  }),\n  createElement('path', {\n    id: 'path894',\n    fill: '#CCCCCC',\n    d: 'M406.474,868.395c0,0,13.066-36.019,5.298-55.794c0,0,20.129,38.139,12.007,57.913  c0,0-0.706-18.361-7.77-27.189C416.009,843.323,408.946,865.923,406.474,868.395z'\n  }),\n  createElement('path', {\n    id: 'path898',\n    fill: '#CCCCCC',\n    d: 'M380.343,863.805c0,0,9.534-15.538-4.591-48.024c0,0-1.413,36.019-13.419,55.439  C362.333,871.22,387.405,835.554,380.343,863.805z'\n  }),\n  createElement('path', {\n    id: 'path902',\n    fill: '#CCCCCC',\n    d: 'M362.686,860.273c0,0-0.353-35.313,0.354-40.61c0,0-6.709,29.31-24.719,46.26  C338.32,865.923,363.745,844.735,362.686,860.273z'\n  }),\n  createElement('path', {\n    id: 'path906',\n    fill: '#CCCCCC',\n    d: 'M345.736,803.771c0,0,10.594,24.014-7.063,56.502c0,0,11.301-21.541,2.825-33.9  C341.498,826.373,346.089,820.369,345.736,803.771z'\n  }),\n  createElement('path', {\n    id: 'path910',\n    fill: '#CCCCCC',\n    d: 'M311.836,859.566c0,0-1.766-27.545,1.412-31.429c0,0,0.354-11.301-0.354-13.065  c0,0,7.063-10.946,7.416,2.119c0,0,2.473,13.771,7.416,21.894c0,0,6.356,9.535,6.003,20.835  C333.729,859.92,316.073,806.598,311.836,859.566z'\n  }),\n  createElement('path', {\n    id: 'path914',\n    fill: '#CCCCCC',\n    d: 'M305.479,810.835c0,0-11.653,19.069-14.831,52.616c0,0-2.472-10.947,4.237-36.372  C294.885,827.079,302.301,799.888,305.479,810.835z'\n  }),\n  createElement('path', {\n    id: 'path918',\n    fill: '#CCCCCC',\n    d: 'M266.988,845.795c0,0,8.828-9.535,11.3-18.363c0,0,6.356-27.896-4.943-12.712  c0,0,0.353,14.125-14.125,27.19C259.219,841.91,267.694,837.673,266.988,845.795z'\n  }),\n  createElement('path', {\n    id: 'path922',\n    fill: '#CCCCCC',\n    d: 'M256.748,836.967c0,0,6.003-30.723,7.416-32.135c0,0,3.178-6.003-1.766-0.354  c0,0-15.538,33.9-22.6,45.555C239.797,850.032,253.922,833.788,256.748,836.967z'\n  }),\n  createElement('path', {\n    id: 'path926',\n    fill: '#CCCCCC',\n    d: 'M246.507,807.657c0,0,20.481-39.552-18.01,6.003  C228.497,813.66,247.919,796.356,246.507,807.657z'\n  }),\n  createElement('path', {\n    id: 'path930',\n    fill: '#CCCCCC',\n    d: 'M219.316,781.879c0,0,8.475-33.193,13.065-32.842c0,0,14.479-15.891,2.825,2.825  c0,0-10.594,16.95-9.535,34.254C225.672,786.116,224.613,769.166,219.316,781.879z'\n  }),\n  createElement('path', {\n    id: 'path934',\n    fill: '#CCCCCC',\n    d: 'M802.508,761.748c0,0-21.188-17.656-25.602-23.836c0,0,23.836,32.664,23.836,45.023  C800.742,782.938,805.156,769.693,802.508,761.748z'\n  }),\n  createElement('path', {\n    id: 'path938',\n    fill: '#CCCCCC',\n    d: 'M812.219,722.904c0,0-37.078-26.484-43.259-39.728c0,0,46.79,52.086,46.79,60.031  C815.75,743.209,816.633,727.318,812.219,722.904z'\n  }),\n  createElement('path', {\n    id: 'path942',\n    fill: '#CCCCCC',\n    d: 'M842.234,450.995c0,0-21.188-14.125-23.836-10.594c0,0,18.539,11.477,22.952,26.483  C841.352,466.886,838.703,450.995,842.234,450.995z'\n  }),\n  createElement('path', { id: 'path946', fill: '#CCCCCC', d: 'M857.242,593.13l-30.898-21.188c0,0,33.547,30.017,34.431,37.079L857.242,593.13z' }),\n  createElement('path', { id: 'path950', stroke: '#000000', d: 'M167.317,553.402l38.844,8.387' }),\n  createElement('path', { id: 'path954', stroke: '#000000', d: 'M256.041,839.438c0,0-0.883-6.181-16.773,12.358' }),\n  createElement('path', { id: 'path958', stroke: '#000000', d: 'M265.752,848.265c0,0,3.531-11.477-7.946-3.53' }),\n  createElement('path', { id: 'path962', stroke: '#000000', d: 'M361.097,863.271c0,0,2.648-19.422-17.655,3.531' })\n);\nrender(tiger, document.getElementById('app'));\n"
  },
  {
    "path": "docs/svg/tiger.html",
    "content": "<!doctype html>\n<html>\n\t<head>\n\t\t<title>inferno svg tiger</title>\n\t</head>\n\t<body>\n\t\t<div id=\"app\"></div>\n\t\t<script src=\"dist/bundle.js\"></script>\n\t</body>\n</html>\n"
  },
  {
    "path": "docs/uibench/app.js",
    "content": "import { linkEvent, version, render } from 'inferno';\n\nuibench.init('Inferno', version);\n\nfunction shouldDataUpdate(lastProps, nextProps) {\n  return lastProps !== nextProps;\n}\n\nconst SCU_hooks = {\n  onComponentShouldUpdate: shouldDataUpdate\n};\n\nfunction TreeLeaf({ children }) {\n  return (\n    <li $HasTextChildren className=\"TreeLeaf\">\n      {children}\n    </li>\n  );\n}\n\nTreeLeaf.defaultHooks = SCU_hooks;\n\nfunction TreeNode({ data }) {\n  var length = data.children.length;\n  var children = new Array(length);\n\n  for (var i = 0; i < length; i++) {\n    var n = data.children[i];\n    var id = n.id;\n\n    if (n.container) {\n      children[i] = <TreeNode data={n} key={id} />;\n    } else {\n      children[i] = <TreeLeaf key={id}>{id}</TreeLeaf>;\n    }\n  }\n\n  return (\n    <ul $HasKeyedChildren className=\"TreeNode\">\n      {children}\n    </ul>\n  );\n}\n\nTreeNode.defaultHooks = SCU_hooks;\n\nfunction tree(data) {\n  /*\n   * $HasVNodeChildren flag is not needed here, because shape of children is known by the compiler\n   * <div> has static children <TreeNode> so there is no need for $HasVNodeChildren\n   */\n  return (\n    <div className=\"Tree\">\n      <TreeNode data={data.root} />\n    </div>\n  );\n}\n\nfunction AnimBox({ data }) {\n  var time = data.time % 10;\n  var style = 'border-radius:' + time + 'px;' + 'background:rgba(0,0,0,' + (0.5 + time / 10) + ')';\n\n  // We don't need to use $HasVNodeChildren here, because there is no Children\n  return <div data-id={data.id} style={style} className=\"AnimBox\" />;\n}\n\nAnimBox.defaultHooks = SCU_hooks;\n\nfunction anim(data) {\n  var items = data.items;\n  var length = items.length;\n  var children = [];\n\n  for (var i = 0; i < length; i++) {\n    var item = items[i];\n\n    children.push(<AnimBox data={item} key={item.id} />);\n  }\n\n  return (\n    <div $HasKeyedChildren className=\"Anim\">\n      {children}\n    </div>\n  );\n}\n\nfunction onClick(text, e) {\n  console.log('Clicked', text);\n  e.stopPropagation();\n}\n\nfunction TableCell({ children }) {\n  /*\n   * Here we want to optimize for having text child vNode,\n   * It can be done by using $HasVNodeChildren on parent element\n   * and manually calling createTextVNode(value) for the children\n   *\n   * linkEvent is used here to bind the first parameter (text) into second parameter onClick function\n   * linkEvent has benefit of not creating function, it basically returns pre-defined object shape that inferno knows how to handle\n   * the main benefit is that no \".bind\" or arrow function \"() => {}\" is needed. It works well with functional Components\n   */\n  return (\n    <td $HasTextChildren onClick={linkEvent(children, onClick)} className=\"TableCell\">\n      {children}\n    </td>\n  );\n}\n\nTableCell.defaultHooks = SCU_hooks;\n\nfunction TableRow({ data }) {\n  var classes = 'TableRow';\n\n  if (data.active) {\n    classes = 'TableRow active';\n  }\n  var cells = data.props;\n  var length = cells.length + 1;\n  var children = [<TableCell>{'#' + data.id}</TableCell>];\n\n  for (var i = 1; i < length; i++) {\n    children.push(<TableCell>{cells[i - 1]}</TableCell>);\n  }\n\n  /*\n   * Again there is element vNode which children is always constant shape.\n   * Add optimization flags for Children type\n   * This time childrens does not have key, so the type is $HasNonKeyedChildren\n   */\n  return (\n    <tr data-id={data.id} className={classes} $HasNonKeyedChildren>\n      {children}\n    </tr>\n  );\n}\n\nTableRow.defaultHooks = SCU_hooks;\n\nfunction table(data) {\n  var items = data.items;\n  var length = items.length;\n  var children = [];\n\n  for (var i = 0; i < length; i++) {\n    var item = items[i];\n\n    // Components does not need ChildrenType flags, it does not hurt, but gains nothing\n    // Because Component children will be passed through props and will not be normalized before rendering anyway\n    children.push(<TableRow data={item} key={item.id} />);\n  }\n\n  /*\n   * When its known that given element has only one type of children we can optimize this compile time\n   * by adding children type $HasKeyedChildren (list of children - all keyed)\n   * $HasKeyedChildren means that there are no holes in the children array and all keys are correctly set\n   */\n  return (\n    <table $HasKeyedChildren className=\"Table\">\n      {children}\n    </table>\n  );\n}\n\nfunction main(data) {\n  var location = data.location;\n  var section;\n\n  if (location === 'table') {\n    section = table(data.table);\n  } else if (location === 'anim') {\n    section = anim(data.anim);\n  } else if (location === 'tree') {\n    section = tree(data.tree);\n  }\n\n  /*\n   * We know that this div will always have single vNode as its children,\n   * so we can optimize here and add flag $NoNormalize\n   */\n  return (\n    <div $HasVNodeChildren className=\"Main\">\n      {section}\n    </div>\n  );\n}\n\ndocument.addEventListener('DOMContentLoaded', function (e) {\n  var container = document.querySelector('#App');\n\n  uibench.run(\n    function (state) {\n      render(main(state), container);\n    },\n    function (samples) {\n      render(<pre $HasTextChildren>{JSON.stringify(samples, null, ' ')}</pre>, container);\n    }\n  );\n});\n"
  },
  {
    "path": "docs/uibench/custom-uibench.js",
    "content": "(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n    typeof define === 'function' && define.amd ? define(['exports'], factory) :\n      (factory((global.uibench = global.uibench || {})));\n}(this, function (exports) { 'use strict';\n\n  var TableAlphabetLength = 10;\n  var TableAlphabets = [\n    \"0123456789\",\n    \"3057846291\",\n    \"8356294107\",\n    \"0861342795\",\n  ];\n  var HomeState = (function () {\n    function HomeState() {\n    }\n    HomeState.prototype.clone = function () {\n      return this;\n    };\n    return HomeState;\n  }());\n  var TableItemState = (function () {\n    function TableItemState(id, active, props) {\n      this.id = id;\n      this.active = active;\n      this.props = props;\n    }\n    TableItemState.prototype.clone = function () {\n      return new TableItemState(this.id, this.active, this.props.slice(0));\n    };\n    TableItemState.create = function (active, props) {\n      return new TableItemState(TableItemState._nextId++, active, props);\n    };\n    TableItemState._nextId = 0;\n    return TableItemState;\n  }());\n  var TableState = (function () {\n    function TableState(items) {\n      this.items = items;\n    }\n    TableState.prototype.clone = function () {\n      return new TableState(this.items.map(function (i) { return i.clone(); }));\n    };\n    TableState.create = function (rows, cols) {\n      var items = [];\n      for (var i = 0; i < rows; i++) {\n        var props = [];\n        for (var j = 0; j < cols; j++) {\n          var str = \"\";\n          var n = i;\n          var alphabet = TableAlphabets[j];\n          while (n >= TableAlphabetLength) {\n            str += alphabet[n % TableAlphabetLength];\n            n = n / TableAlphabetLength | 0;\n          }\n          str += alphabet[n % TableAlphabetLength];\n          props.push(str);\n        }\n        items.push(TableItemState.create(false, props));\n      }\n      return new TableState(items);\n    };\n    return TableState;\n  }());\n  var AnimBoxState = (function () {\n    function AnimBoxState(id, time) {\n      this.id = id;\n      this.time = time;\n    }\n    AnimBoxState.prototype.clone = function () {\n      return new AnimBoxState(this.id, this.time);\n    };\n    AnimBoxState.create = function (time) {\n      return new AnimBoxState(AnimBoxState._nextId++, time);\n    };\n    AnimBoxState._nextId = 0;\n    return AnimBoxState;\n  }());\n  var AnimState = (function () {\n    function AnimState(items) {\n      this.items = items;\n    }\n    AnimState.prototype.clone = function () {\n      return new AnimState(this.items.map(function (i) { return i.clone(); }));\n    };\n    AnimState.create = function (count) {\n      var items = [];\n      for (var i = 0; i < count; i++) {\n        items.push(AnimBoxState.create(0));\n      }\n      return new AnimState(items);\n    };\n    return AnimState;\n  }());\n  var TreeNodeState = (function () {\n    function TreeNodeState(id, container, children) {\n      this.id = id;\n      this.container = container;\n      this.children = children;\n    }\n    TreeNodeState.prototype.clone = function () {\n      return new TreeNodeState(this.id, this.container, this.children ? this.children.map(function (i) { return i.clone(); }) : this.children);\n    };\n    TreeNodeState.create = function (container, children) {\n      return new TreeNodeState(TreeNodeState._nextId++, container, children);\n    };\n    TreeNodeState._nextId = 0;\n    return TreeNodeState;\n  }());\n  var TreeState = (function () {\n    function TreeState(root) {\n      this.root = root;\n    }\n    TreeState.prototype.clone = function () {\n      return new TreeState(this.root.clone());\n    };\n    TreeState.create = function (hierarchy) {\n      function _create(depth) {\n        var count = hierarchy[depth];\n        var children = [];\n        if (depth === (hierarchy.length - 1)) {\n          for (var i = 0; i < count; i++) {\n            children.push(TreeNodeState.create(false, null));\n          }\n        }\n        else {\n          for (var i = 0; i < count; i++) {\n            children.push(TreeNodeState.create(true, _create(depth + 1)));\n          }\n        }\n        return children;\n      }\n      return new TreeState(TreeNodeState.create(true, _create(0)));\n    };\n    return TreeState;\n  }());\n  var AppState = (function () {\n    function AppState(location, home, table, anim, tree) {\n      this.location = location;\n      this.home = home;\n      this.table = table;\n      this.anim = anim;\n      this.tree = tree;\n    }\n    AppState.prototype.clone = function () {\n      return new AppState(this.location, this.home.clone(), this.table.clone(), this.anim.clone(), this.tree.clone());\n    };\n    return AppState;\n  }());\n\n  function switchTo(state, location) {\n    if (state.location === location) {\n      return state;\n    }\n    else {\n      return new AppState(location, state.home, state.table, state.anim, state.tree);\n    }\n  }\n  function tableCreate(state, rows, cols) {\n    return new AppState(state.location, state.home, TableState.create(rows, cols), state.anim, state.tree);\n  }\n  function tableFilterBy(state, nth) {\n    return new AppState(state.location, state.home, new TableState(state.table.items.filter(function (item, i) { return (i + 1) % nth; })), state.anim, state.tree);\n  }\n  function tableSortBy(state, i) {\n    var newItems = state.table.items.slice();\n    newItems.sort(function (a, b) { return a.props[i].localeCompare(b.props[i]); });\n    return new AppState(state.location, state.home, new TableState(newItems), state.anim, state.tree);\n  }\n  function tableActivateEach(state, nth) {\n    return new AppState(state.location, state.home, new TableState(state.table.items.map(function (item, i) { return (i + 1) % nth ?\n      item :\n      new TableItemState(item.id, true, item.props); })), state.anim, state.tree);\n  }\n  function animAdvanceEach(state, nth) {\n    return new AppState(state.location, state.home, state.table, new AnimState(state.anim.items.map(function (item, i) { return (i + 1) % nth ? item : new AnimBoxState(item.id, item.time + 1); })), state.tree);\n  }\n  function treeCreate(state, hierarchy) {\n    return new AppState(state.location, state.home, state.table, state.anim, TreeState.create(hierarchy));\n  }\n  function treeTransform(state, transformers) {\n    function transform(node, depth) {\n      var t = transformers[depth];\n      if (node.children !== null) {\n        var children = t(node.children);\n        if (depth < (transformers.length - 1)) {\n          children.map(function (item) { return transform(item, depth + 1); });\n        }\n        return new TreeNodeState(node.id, node.container, children);\n      }\n      return new TreeNodeState(node.id, node.container, null);\n    }\n    return new AppState(state.location, state.home, state.table, state.anim, new TreeState(transform(state.tree.root, 0)));\n  }\n\n  function reverse(children) {\n    var r = children.slice();\n    r.reverse();\n    return r;\n  }\n  function snabbdomWorstCase(children) {\n    var r = children.slice();\n    var a = r.shift();\n    var b = r.splice(r.length - 2, 1);\n    r.push(a, b[0]);\n    return r;\n  }\n  function insertFirst(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.unshift(TreeNodeState.create(false, null));\n      }\n      return children;\n    };\n  }\n  function insertLast(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.push(TreeNodeState.create(false, null));\n      }\n      return children;\n    };\n  }\n  function removeFirst(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.shift();\n      }\n      return children;\n    };\n  }\n  function removeLast(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.pop();\n      }\n      return children;\n    };\n  }\n  function moveFromEndToStart(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.unshift(children.pop());\n      }\n      return children;\n    };\n  }\n  function moveFromStartToEnd(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.push(children.shift());\n      }\n      return children;\n    };\n  }\n\n  function tableTests(onUpdate) {\n    var state = tableActivateEach(new AppState(\"table\", new HomeState(), TableState.create(2, 2), AnimState.create(0), TreeState.create([0])), 2);\n    state.table.items[0].id = 300;\n    state.table.items[1].id = 301;\n    onUpdate(state, \"update\");\n    // var table = document.getElementsByClassName(\"Table\");\n    // if (table.length !== 1) {\n    //   throw new Error(\"Spec test failed: table with Table className doesn't exists\");\n    // }\n    // var rows = document.getElementsByClassName(\"TableRow\");\n    // if (rows.length !== 2) {\n    //   throw new Error(\"Spec test failed: invalid number of TableRows\");\n    // }\n    // if (rows[0].getAttribute(\"data-id\") !== \"300\") {\n    //   throw new Error(\"Spec test failed: invalid data-id attribute in the TableRow\");\n    // }\n    // if (rows[1].className.indexOf(\"active\") === -1) {\n    //   throw new Error(\"Spec test failed: TableRow should have active className when it is activated\");\n    // }\n    // var cells = document.getElementsByClassName(\"TableCell\");\n    // if (cells.length !== 6) {\n    //   throw new Error(\"Spec test failed: invalid number of TableCells\");\n    // }\n    // if (cells[0].textContent !== \"#300\") {\n    //   throw new Error(\"Spec test failed: invalid textContent in the id TableCell\");\n    // }\n    // if (cells[1].textContent !== \"0\") {\n    //   throw new Error(\"Spec test failed: invalid textContent in the data TableCell\");\n    // }\n    // if (cells[2].textContent !== \"3\") {\n    //   throw new Error(\"Spec test failed: invalid textContent in the data TableCell\");\n    // }\n    // var logFn = console.log;\n    // var clicked = false;\n    // console.log = function () {\n    //   clicked = true;\n    // };\n    // cells[1].click();\n    // console.log = logFn;\n    // if (clicked === false) {\n    //   throw new Error(\"Spec test failed: TableCell doesn't have onClick event listener that prints to the console\");\n    // }\n  }\n  function animTests(onUpdate) {\n    var state = new AppState(\"anim\", new HomeState(), TableState.create(0, 0), AnimState.create(2), TreeState.create([0]));\n    state.anim.items[0].id = 100;\n    state.anim.items[1].id = 101;\n    state = animAdvanceEach(state, 2);\n    onUpdate(state, \"update\");\n    // var anim = document.getElementsByClassName(\"Anim\");\n    // if (anim.length !== 1) {\n    //   throw new Error(\"Spec test failed: div with Anim className doesn't exists\");\n    // }\n    // var boxes = document.getElementsByClassName(\"AnimBox\");\n    // if (boxes.length !== 2) {\n    //   throw new Error(\"Spec test failed: invalid number of AnimBoxes\");\n    // }\n    // if (boxes[0].getAttribute(\"data-id\") !== \"100\") {\n    //   throw new Error(\"Spec test failed: invalid data-id attribute in the AnimBox\");\n    // }\n    // if (boxes[0].style.borderRadius !== \"0px\") {\n    //   throw new Error(\"Spec test failed: invalid borderRadius style in the AnimBox\");\n    // }\n    // if (boxes[1].style.borderRadius !== \"1px\") {\n    //   throw new Error(\"Spec test failed: invalid borderRadius style in the AnimBox\");\n    // }\n    // if (!boxes[0].style.background) {\n    //   throw new Error(\"Spec test failed: invalid background style in the AnimBox\");\n    // }\n  }\n  function treeTests(onUpdate) {\n    var state = new AppState(\"tree\", new HomeState(), TableState.create(0, 0), AnimState.create(0), TreeState.create([1, 2]));\n    state.tree.root.children[0].children[0].id = 2081;\n    state.tree.root.children[0].children[1].id = 2082;\n    onUpdate(state, \"update\");\n    // var tree = document.getElementsByClassName(\"Tree\");\n    // if (tree.length !== 1) {\n    //   throw new Error(\"Spec test failed: div with Tree className doesn't exists\");\n    // }\n    // var treeNodes = document.getElementsByClassName(\"TreeNode\");\n    // if (treeNodes.length !== 2) {\n    //   throw new Error(\"Spec test failed: invalid number of TreeNodes\");\n    // }\n    // var treeLeafs = document.getElementsByClassName(\"TreeLeaf\");\n    // if (treeLeafs.length !== 2) {\n    //   throw new Error(\"Spec test failed: invalid number of TreeLeafs\");\n    // }\n    // if (treeLeafs[0].textContent !== \"2081\") {\n    //   throw new Error(\"Spec test failed: invalid textContent in the TreeLeaf\");\n    // }\n    // if (treeLeafs[1].textContent !== \"2082\") {\n    //   throw new Error(\"Spec test failed: invalid textContent in the TreeLeaf\");\n    // }\n  }\n  function specTest(onUpdate) {\n    var state = new AppState(\"table\", new HomeState(), TableState.create(0, 0), AnimState.create(0), TreeState.create([0]));\n    onUpdate(state, \"init\");\n    var mainTag = document.getElementsByClassName(\"Main\");\n    // if (mainTag.length !== 1) {\n    //   throw new Error(\"Spec test failed: div tag with Main className doesn\\\"t exists\");\n    // }\n    tableTests(onUpdate);\n    animTests(onUpdate);\n    treeTests(onUpdate);\n  }\n  function scuTest(onUpdate, onFinish) {\n    var state = new AppState(\"table\", new HomeState(), TableState.create(1, 1), AnimState.create(0), TreeState.create([0]));\n    state.table.items[0].props[0] = \"a\";\n    onUpdate(state, \"init\");\n    // var node = document.getElementsByClassName(\"TableCell\")[1];\n    // if (!node || node.textContent !== \"a\") {\n    //   throw new Error(\"SCU test failed\");\n    // }\n    // state.table.items[0].props[0] = \"b\";\n    // onUpdate(state, \"update\");\n    // node = document.getElementsByClassName(\"TableCell\")[1];\n    // if (!node) {\n    //   throw new Error(\"SCU test failed\");\n    // }\n    // var result = true;\n    // if (node.textContent !== \"a\") {\n    //   if (node.textContent === \"b\") {\n    //     result = false;\n    //   }\n    //   else {\n    //     throw new Error(\"SCU test failed\");\n    //   }\n    // }\n    window.requestAnimationFrame(function () {\n      onFinish(true);\n    });\n  }\n  function recyclingTest(onUpdate, onFinish) {\n    // var initialState = new AppState(\"tree\", new HomeState(), TableState.create(0, 0), AnimState.create(0), TreeState.create([0]));\n    // var toState = treeCreate(initialState, [1]);\n    // onUpdate(initialState, \"init\");\n    // onUpdate(toState, \"update\");\n    // var a = document.getElementsByClassName(\"TreeLeaf\")[0];\n    // onUpdate(initialState, \"init\");\n    // onUpdate(toState, \"update\");\n    // var b = document.getElementsByClassName(\"TreeLeaf\")[0];\n    // if (!a || !b) {\n    //   throw new Error(\"recycling test failed\");\n    // }\n    // var result = (a === b);\n    window.requestAnimationFrame(function () {\n      onFinish(false);\n    });\n  }\n  function preserveStateTest(onUpdate, onFinish) {\n    // var state = \"uibench_\" + Math.random();\n    // // Check tables\n    // var tableInit = new AppState(\"table\", new HomeState(), TableState.create(3, 1), AnimState.create(0), TreeState.create([0]));\n    // var tableUpdate = tableFilterBy(tableInit, 2);\n    // onUpdate(tableInit, \"init\");\n    // var tableRows = document.getElementsByClassName(\"TableRow\");\n    // tableRows[2]._uibenchState = state;\n    // onUpdate(tableUpdate, \"init\");\n    // tableRows = document.getElementsByClassName(\"TableRow\");\n    // var result = tableRows[1]._uibenchState === state;\n    // // Check trees\n    // var treeInit = new AppState(\"tree\", new HomeState(), TableState.create(0, 0), AnimState.create(0), TreeState.create([2]));\n    // var treeUpdate = treeTransform(treeInit, [reverse]);\n    // onUpdate(treeInit, \"init\");\n    // var treeLeafs = document.getElementsByClassName(\"TreeLeaf\");\n    // treeLeafs[0]._uibenchState = state;\n    // onUpdate(treeUpdate, \"update\");\n    // treeLeafs = document.getElementsByClassName(\"TreeLeaf\");\n    // result = result && (treeLeafs[1]._uibenchState === state);\n    window.requestAnimationFrame(function () {\n      onFinish(true);\n    });\n  }\n\n  // performance.now() polyfill\n  // https://gist.github.com/paulirish/5438650\n  // prepare base perf object\n  if (typeof window.performance === \"undefined\") {\n    window.performance = {};\n  }\n  if (!window.performance.now) {\n    var nowOffset_1 = Date.now();\n    if (window.performance.timing && window.performance.timing.navigationStart) {\n      nowOffset_1 = window.performance.timing.navigationStart;\n    }\n    window.performance.now = function now() {\n      return Date.now() - nowOffset_1;\n    };\n  }\n  var TestCase = (function () {\n    function TestCase(name, from, to) {\n      this.name = name;\n      this.from = from;\n      this.to = to;\n    }\n    return TestCase;\n  }());\n  function testCase(name, from, to) {\n    return new TestCase(name, from, to);\n  }\n  var config = {\n    tests: null,\n    iterations: 5,\n    name: \"unnamed\",\n    version: \"0.0.0\",\n    report: false,\n    mobile: false,\n    disableSCU: false,\n    enableDOMRecycling: false,\n    filter: null,\n    fullRenderTime: false,\n    timelineMarks: false,\n    disableChecks: false,\n    startDelay: 0,\n  };\n  var timing = {\n    start: 0,\n    run: 0,\n    firstRender: 0,\n  };\n  var memory = {\n    initial: performance.memory === undefined ? 0 : performance.memory.usedJSHeapSize,\n    start: 0,\n    max: 0,\n  };\n  function parseQueryString(a) {\n    if (a.length === 0) {\n      return {};\n    }\n    var b = {};\n    for (var i = 0; i < a.length; ++i) {\n      var p = a[i].split(\"=\", 2);\n      if (p.length === 1) {\n        b[p[0]] = \"\";\n      }\n      else {\n        b[p[0]] = decodeURIComponent(p[1].replace(/\\+/g, \" \"));\n      }\n    }\n    return b;\n  }\n  function scuClone(state) {\n    if (config.disableSCU) {\n      state = state.clone();\n    }\n    return state;\n  }\n  function init(name, version) {\n    config.name = name;\n    config.version = version;\n    var qs = parseQueryString(window.location.search.substr(1).split(\"&\"));\n    if (qs[\"i\"] !== undefined) {\n      config.iterations = parseInt(qs[\"i\"], 10);\n    }\n    if (qs[\"name\"] !== undefined) {\n      config.name = qs[\"name\"];\n    }\n    if (qs[\"version\"] !== undefined) {\n      config.version = qs[\"version\"];\n    }\n    if (qs[\"report\"] !== undefined) {\n      config.report = true;\n    }\n    if (qs[\"mobile\"] !== undefined) {\n      config.mobile = true;\n    }\n    if (qs[\"disableSCU\"] !== undefined) {\n      config.disableSCU = true;\n    }\n    if (qs[\"enableDOMRecycling\"] !== undefined) {\n      config.enableDOMRecycling = true;\n    }\n    if (qs[\"filter\"] !== undefined) {\n      config.filter = qs[\"filter\"];\n    }\n    if (qs[\"fullRenderTime\"] !== undefined) {\n      config.fullRenderTime = true;\n    }\n    if (qs[\"timelineMarks\"] !== undefined) {\n      config.timelineMarks = true;\n    }\n    if (qs[\"disableChecks\"] !== undefined) {\n      config.disableChecks = true;\n    }\n    if (qs[\"startDelay\"] !== undefined) {\n      config.startDelay = parseInt(qs[\"startDelay\"], 10);\n    }\n    return config;\n  }\n  function initTests() {\n    var initial = new AppState(\"home\", new HomeState(), TableState.create(0, 0), AnimState.create(config.mobile ? 30 : 100), TreeState.create([0]));\n    var initialTable = switchTo(initial, \"table\");\n    var initialAnim = switchTo(initial, \"anim\");\n    var initialTree = switchTo(initial, \"tree\");\n    if (config.disableSCU) {\n      initialTable = initialTable.clone();\n      initialAnim = initialAnim.clone();\n      initialTree = initialTree.clone();\n    }\n    if (config.mobile) {\n      var table30_4 = tableCreate(initialTable, 30, 4);\n      var table15_4 = tableCreate(initialTable, 15, 4);\n      var table30_2 = tableCreate(initialTable, 30, 2);\n      var table15_2 = tableCreate(initialTable, 15, 2);\n      var tree50 = treeCreate(initialTree, [50]);\n      var tree5_10 = treeCreate(initialTree, [5, 10]);\n      var tree10_5 = treeCreate(initialTree, [10, 5]);\n      var tree10_10_10_2 = treeCreate(initialTree, [10, 10, 10, 2]);\n      var tree2__9 = treeCreate(initialTree, [2, 2, 2, 2, 2, 2, 2, 2, 2]);\n      if (config.disableSCU) {\n        table30_4 = table30_4.clone();\n        table15_4 = table15_4.clone();\n        table30_2 = table30_2.clone();\n        table15_2 = table15_2.clone();\n        tree50 = tree50.clone();\n        tree5_10 = tree5_10.clone();\n        tree10_5 = tree10_5.clone();\n      }\n      config.tests = [\n        testCase(\"table/[30,4]/render\", initialTable, scuClone(table30_4)),\n        testCase(\"table/[15,4]/render\", initialTable, scuClone(table15_4)),\n        testCase(\"table/[30,2]/render\", initialTable, scuClone(table30_2)),\n        testCase(\"table/[15,2]/render\", initialTable, scuClone(table15_2)),\n        testCase(\"table/[30,4]/removeAll\", table30_4, scuClone(initialTable)),\n        testCase(\"table/[15,4]/removeAll\", table15_4, scuClone(initialTable)),\n        testCase(\"table/[30,2]/removeAll\", table30_2, scuClone(initialTable)),\n        testCase(\"table/[15,2]/removeAll\", table15_2, scuClone(initialTable)),\n        testCase(\"table/[30,4]/sort/0\", table30_4, scuClone(tableSortBy(table30_4, 0))),\n        testCase(\"table/[15,4]/sort/0\", table15_4, scuClone(tableSortBy(table15_4, 0))),\n        testCase(\"table/[30,2]/sort/0\", table30_2, scuClone(tableSortBy(table30_2, 0))),\n        testCase(\"table/[15,2]/sort/0\", table15_2, scuClone(tableSortBy(table15_2, 0))),\n        testCase(\"table/[30,4]/sort/1\", table30_4, scuClone(tableSortBy(table30_4, 1))),\n        testCase(\"table/[15,4]/sort/1\", table15_4, scuClone(tableSortBy(table15_4, 1))),\n        testCase(\"table/[30,2]/sort/1\", table30_2, scuClone(tableSortBy(table30_2, 1))),\n        testCase(\"table/[15,2]/sort/1\", table15_2, scuClone(tableSortBy(table15_2, 1))),\n        testCase(\"table/[30,4]/filter/8\", table30_4, scuClone(tableFilterBy(table30_4, 8))),\n        testCase(\"table/[15,4]/filter/8\", table15_4, scuClone(tableFilterBy(table15_4, 8))),\n        testCase(\"table/[30,2]/filter/8\", table30_2, scuClone(tableFilterBy(table30_2, 8))),\n        testCase(\"table/[15,2]/filter/8\", table15_2, scuClone(tableFilterBy(table15_2, 8))),\n        testCase(\"table/[30,4]/filter/4\", table30_4, scuClone(tableFilterBy(table30_4, 4))),\n        testCase(\"table/[15,4]/filter/4\", table15_4, scuClone(tableFilterBy(table15_4, 4))),\n        testCase(\"table/[30,2]/filter/4\", table30_2, scuClone(tableFilterBy(table30_2, 4))),\n        testCase(\"table/[15,2]/filter/4\", table15_2, scuClone(tableFilterBy(table15_2, 4))),\n        testCase(\"table/[30,4]/filter/2\", table30_4, scuClone(tableFilterBy(table30_4, 2))),\n        testCase(\"table/[15,4]/filter/2\", table15_4, scuClone(tableFilterBy(table15_4, 2))),\n        testCase(\"table/[30,2]/filter/2\", table30_2, scuClone(tableFilterBy(table30_2, 2))),\n        testCase(\"table/[15,2]/filter/2\", table15_2, scuClone(tableFilterBy(table15_2, 2))),\n        testCase(\"table/[30,4]/activate/8\", table30_4, scuClone(tableActivateEach(table30_4, 8))),\n        testCase(\"table/[15,4]/activate/8\", table15_4, scuClone(tableActivateEach(table15_4, 8))),\n        testCase(\"table/[30,2]/activate/8\", table30_2, scuClone(tableActivateEach(table30_2, 8))),\n        testCase(\"table/[15,2]/activate/8\", table15_2, scuClone(tableActivateEach(table15_2, 8))),\n        testCase(\"table/[30,4]/activate/4\", table30_4, scuClone(tableActivateEach(table30_4, 4))),\n        testCase(\"table/[15,4]/activate/4\", table15_4, scuClone(tableActivateEach(table15_4, 4))),\n        testCase(\"table/[30,2]/activate/4\", table30_2, scuClone(tableActivateEach(table30_2, 4))),\n        testCase(\"table/[15,2]/activate/4\", table15_2, scuClone(tableActivateEach(table15_2, 4))),\n        testCase(\"table/[30,4]/activate/2\", table30_4, scuClone(tableActivateEach(table30_4, 2))),\n        testCase(\"table/[15,4]/activate/2\", table15_4, scuClone(tableActivateEach(table15_4, 2))),\n        testCase(\"table/[30,2]/activate/2\", table30_2, scuClone(tableActivateEach(table30_2, 2))),\n        testCase(\"table/[15,2]/activate/2\", table15_2, scuClone(tableActivateEach(table15_2, 2))),\n        testCase(\"anim/30/8\", initialAnim, scuClone(animAdvanceEach(initialAnim, 8))),\n        testCase(\"anim/30/4\", initialAnim, scuClone(animAdvanceEach(initialAnim, 4))),\n        testCase(\"anim/30/2\", initialAnim, scuClone(animAdvanceEach(initialAnim, 2))),\n        testCase(\"tree/[50]/render\", initialTree, scuClone(tree50)),\n        testCase(\"tree/[5,10]/render\", initialTree, scuClone(tree5_10)),\n        testCase(\"tree/[10,5]/render\", initialTree, scuClone(tree10_5)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2,2]/render\", initialTree, scuClone(tree2__9)),\n        testCase(\"tree/[50]/removeAll\", tree50, scuClone(initialTree)),\n        testCase(\"tree/[5,10]/removeAll\", tree5_10, scuClone(initialTree)),\n        testCase(\"tree/[10,5]/removeAll\", tree10_5, scuClone(initialTree)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2,2]/removeAll\", tree2__9, scuClone(initialTree)),\n        testCase(\"tree/[50]/[reverse]\", tree50, scuClone(treeTransform(tree50, [reverse]))),\n        testCase(\"tree/[5,10]/[reverse]\", tree5_10, scuClone(treeTransform(tree5_10, [reverse]))),\n        testCase(\"tree/[10,5]/[reverse]\", tree10_5, scuClone(treeTransform(tree10_5, [reverse]))),\n        testCase(\"tree/[50]/[insertFirst(1)]\", tree50, scuClone(treeTransform(tree50, [insertFirst(1)]))),\n        testCase(\"tree/[5,10]/[insertFirst(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [insertFirst(1)]))),\n        testCase(\"tree/[10,5]/[insertFirst(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [insertFirst(1)]))),\n        testCase(\"tree/[50]/[insertLast(1)]\", tree50, scuClone(treeTransform(tree50, [insertLast(1)]))),\n        testCase(\"tree/[5,10]/[insertLast(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [insertLast(1)]))),\n        testCase(\"tree/[10,5]/[insertLast(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [insertLast(1)]))),\n        testCase(\"tree/[50]/[removeFirst(1)]\", tree50, scuClone(treeTransform(tree50, [removeFirst(1)]))),\n        testCase(\"tree/[5,10]/[removeFirst(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [removeFirst(1)]))),\n        testCase(\"tree/[10,5]/[removeFirst(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [removeFirst(1)]))),\n        testCase(\"tree/[50]/[removeLast(1)]\", tree50, scuClone(treeTransform(tree50, [removeLast(1)]))),\n        testCase(\"tree/[5,10]/[removeLast(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [removeLast(1)]))),\n        testCase(\"tree/[10,5]/[removeLast(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [removeLast(1)]))),\n        testCase(\"tree/[50]/[moveFromEndToStart(1)]\", tree50, scuClone(treeTransform(tree50, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[5,10]/[moveFromEndToStart(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[10,5]/[moveFromEndToStart(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[50]/[moveFromStartToEnd(1)]\", tree50, scuClone(treeTransform(tree50, [moveFromStartToEnd(1)]))),\n        testCase(\"tree/[5,10]/[moveFromStartToEnd(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [moveFromStartToEnd(1)]))),\n        testCase(\"tree/[10,5]/[moveFromStartToEnd(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [moveFromStartToEnd(1)]))),\n        // special use case that should trigger worst case scenario for kivi library\n        testCase(\"tree/[50]/[kivi_worst_case]\", tree50, scuClone(treeTransform(treeTransform(treeTransform(tree50, [removeFirst(1)]), [removeLast(1)]), [reverse]))),\n        // special use case that should trigger worst case scenario for snabbdom library\n        testCase(\"tree/[50]/[snabbdom_worst_case]\", tree50, scuClone(treeTransform(tree50, [snabbdomWorstCase]))),\n        // special use case that should trigger worst case scenario for react library\n        testCase(\"tree/[50]/[react_worst_case]\", tree50, scuClone(treeTransform(treeTransform(treeTransform(tree50, [removeFirst(1)]), [removeLast(1)]), [moveFromEndToStart(1)]))),\n        // special use case that should trigger worst case scenario for virtual-dom library\n        testCase(\"tree/[50]/[virtual_dom_worst_case]\", tree50, scuClone(treeTransform(tree50, [moveFromStartToEnd(2)]))),\n        // test case with large amount of vnodes to test diff overhead\n        testCase(\"tree/[10,10,10,2]/no_change\", tree10_10_10_2, scuClone(tree10_10_10_2)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2]/no_change\", tree2__9, scuClone(tree2__9)),\n      ];\n    }\n    else {\n      var table100_4 = tableCreate(initialTable, 100, 4);\n      var table50_4 = tableCreate(initialTable, 50, 4);\n      var table100_2 = tableCreate(initialTable, 100, 2);\n      var table50_2 = tableCreate(initialTable, 50, 2);\n      var tree500 = treeCreate(initialTree, [500]);\n      var tree50_10 = treeCreate(initialTree, [50, 10]);\n      var tree10_50 = treeCreate(initialTree, [10, 50]);\n      var tree5_100 = treeCreate(initialTree, [5, 100]);\n      var tree10__4 = treeCreate(initialTree, [10, 10, 10, 10]);\n      var tree2__10 = treeCreate(initialTree, [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]);\n      if (config.disableSCU) {\n        table100_4 = table100_4.clone();\n        table50_4 = table50_4.clone();\n        table100_2 = table100_2.clone();\n        table50_2 = table50_2.clone();\n        tree500 = tree500.clone();\n        tree50_10 = tree50_10.clone();\n        tree10_50 = tree10_50.clone();\n        tree5_100 = tree5_100.clone();\n      }\n      config.tests = [\n        testCase(\"table/[100,4]/render\", initialTable, scuClone(table100_4)),\n        testCase(\"table/[50,4]/render\", initialTable, scuClone(table50_4)),\n        testCase(\"table/[100,2]/render\", initialTable, scuClone(table100_2)),\n        testCase(\"table/[50,2]/render\", initialTable, scuClone(table50_2)),\n        testCase(\"table/[100,4]/removeAll\", table100_4, scuClone(initialTable)),\n        testCase(\"table/[50,4]/removeAll\", table50_4, scuClone(initialTable)),\n        testCase(\"table/[100,2]/removeAll\", table100_2, scuClone(initialTable)),\n        testCase(\"table/[50,2]/removeAll\", table50_2, scuClone(initialTable)),\n        testCase(\"table/[100,4]/sort/0\", table100_4, scuClone(tableSortBy(table100_4, 0))),\n        testCase(\"table/[50,4]/sort/0\", table50_4, scuClone(tableSortBy(table50_4, 0))),\n        testCase(\"table/[100,2]/sort/0\", table100_2, scuClone(tableSortBy(table100_2, 0))),\n        testCase(\"table/[50,2]/sort/0\", table50_2, scuClone(tableSortBy(table50_2, 0))),\n        testCase(\"table/[100,4]/sort/1\", table100_4, scuClone(tableSortBy(table100_4, 1))),\n        testCase(\"table/[50,4]/sort/1\", table50_4, scuClone(tableSortBy(table50_4, 1))),\n        testCase(\"table/[100,2]/sort/1\", table100_2, scuClone(tableSortBy(table100_2, 1))),\n        testCase(\"table/[50,2]/sort/1\", table50_2, scuClone(tableSortBy(table50_2, 1))),\n        testCase(\"table/[100,4]/filter/32\", table100_4, scuClone(tableFilterBy(table100_4, 32))),\n        testCase(\"table/[50,4]/filter/32\", table50_4, scuClone(tableFilterBy(table50_4, 32))),\n        testCase(\"table/[100,2]/filter/32\", table100_2, scuClone(tableFilterBy(table100_2, 32))),\n        testCase(\"table/[50,2]/filter/32\", table50_2, scuClone(tableFilterBy(table50_2, 32))),\n        testCase(\"table/[100,4]/filter/16\", table100_4, scuClone(tableFilterBy(table100_4, 16))),\n        testCase(\"table/[50,4]/filter/16\", table50_4, scuClone(tableFilterBy(table50_4, 16))),\n        testCase(\"table/[100,2]/filter/16\", table100_2, scuClone(tableFilterBy(table100_2, 16))),\n        testCase(\"table/[50,2]/filter/16\", table50_2, scuClone(tableFilterBy(table50_2, 16))),\n        testCase(\"table/[100,4]/filter/8\", table100_4, scuClone(tableFilterBy(table100_4, 8))),\n        testCase(\"table/[50,4]/filter/8\", table50_4, scuClone(tableFilterBy(table50_4, 8))),\n        testCase(\"table/[100,2]/filter/8\", table100_2, scuClone(tableFilterBy(table100_2, 8))),\n        testCase(\"table/[50,2]/filter/8\", table50_2, scuClone(tableFilterBy(table50_2, 8))),\n        testCase(\"table/[100,4]/filter/4\", table100_4, scuClone(tableFilterBy(table100_4, 4))),\n        testCase(\"table/[50,4]/filter/4\", table50_4, scuClone(tableFilterBy(table50_4, 4))),\n        testCase(\"table/[100,2]/filter/4\", table100_2, scuClone(tableFilterBy(table100_2, 4))),\n        testCase(\"table/[50,2]/filter/4\", table50_2, scuClone(tableFilterBy(table50_2, 4))),\n        testCase(\"table/[100,4]/activate/32\", table100_4, scuClone(tableActivateEach(table100_4, 32))),\n        testCase(\"table/[50,4]/activate/32\", table50_4, scuClone(tableActivateEach(table50_4, 32))),\n        testCase(\"table/[100,2]/activate/32\", table100_2, scuClone(tableActivateEach(table100_2, 32))),\n        testCase(\"table/[50,2]/activate/32\", table50_2, scuClone(tableActivateEach(table50_2, 32))),\n        testCase(\"table/[100,4]/activate/16\", table100_4, scuClone(tableActivateEach(table100_4, 16))),\n        testCase(\"table/[50,4]/activate/16\", table50_4, scuClone(tableActivateEach(table50_4, 16))),\n        testCase(\"table/[100,2]/activate/16\", table100_2, scuClone(tableActivateEach(table100_2, 16))),\n        testCase(\"table/[50,2]/activate/16\", table50_2, scuClone(tableActivateEach(table50_2, 16))),\n        testCase(\"table/[100,4]/activate/8\", table100_4, scuClone(tableActivateEach(table100_4, 8))),\n        testCase(\"table/[50,4]/activate/8\", table50_4, scuClone(tableActivateEach(table50_4, 8))),\n        testCase(\"table/[100,2]/activate/8\", table100_2, scuClone(tableActivateEach(table100_2, 8))),\n        testCase(\"table/[50,2]/activate/8\", table50_2, scuClone(tableActivateEach(table50_2, 8))),\n        testCase(\"table/[100,4]/activate/4\", table100_4, scuClone(tableActivateEach(table100_4, 4))),\n        testCase(\"table/[50,4]/activate/4\", table50_4, scuClone(tableActivateEach(table50_4, 4))),\n        testCase(\"table/[100,2]/activate/4\", table100_2, scuClone(tableActivateEach(table100_2, 4))),\n        testCase(\"table/[50,2]/activate/4\", table50_2, scuClone(tableActivateEach(table50_2, 4))),\n        testCase(\"anim/100/32\", initialAnim, scuClone(animAdvanceEach(initialAnim, 32))),\n        testCase(\"anim/100/16\", initialAnim, scuClone(animAdvanceEach(initialAnim, 16))),\n        testCase(\"anim/100/8\", initialAnim, scuClone(animAdvanceEach(initialAnim, 8))),\n        testCase(\"anim/100/4\", initialAnim, scuClone(animAdvanceEach(initialAnim, 4))),\n        testCase(\"tree/[500]/render\", initialTree, scuClone(tree500)),\n        testCase(\"tree/[50,10]/render\", initialTree, scuClone(tree50_10)),\n        testCase(\"tree/[10,50]/render\", initialTree, scuClone(tree10_50)),\n        testCase(\"tree/[5,100]/render\", initialTree, scuClone(tree5_100)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2,2,2]/render\", initialTree, scuClone(tree2__10)),\n        testCase(\"tree/[500]/removeAll\", tree500, scuClone(initialTree)),\n        testCase(\"tree/[50,10]/removeAll\", tree50_10, scuClone(initialTree)),\n        testCase(\"tree/[10,50]/removeAll\", tree10_50, scuClone(initialTree)),\n        testCase(\"tree/[5,100]/removeAll\", tree5_100, scuClone(initialTree)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2,2,2]/removeAll\", tree2__10, scuClone(initialTree)),\n        testCase(\"tree/[500]/[reverse]\", tree500, scuClone(treeTransform(tree500, [reverse]))),\n        testCase(\"tree/[50,10]/[reverse]\", tree50_10, scuClone(treeTransform(tree50_10, [reverse]))),\n        testCase(\"tree/[10,50]/[reverse]\", tree10_50, scuClone(treeTransform(tree10_50, [reverse]))),\n        testCase(\"tree/[5,100]/[reverse]\", tree5_100, scuClone(treeTransform(tree5_100, [reverse]))),\n        testCase(\"tree/[500]/[insertFirst(1)]\", tree500, scuClone(treeTransform(tree500, [insertFirst(1)]))),\n        testCase(\"tree/[50,10]/[insertFirst(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [insertFirst(1)]))),\n        testCase(\"tree/[10,50]/[insertFirst(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [insertFirst(1)]))),\n        testCase(\"tree/[5,100]/[insertFirst(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [insertFirst(1)]))),\n        testCase(\"tree/[500]/[insertLast(1)]\", tree500, scuClone(treeTransform(tree500, [insertLast(1)]))),\n        testCase(\"tree/[50,10]/[insertLast(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [insertLast(1)]))),\n        testCase(\"tree/[10,50]/[insertLast(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [insertLast(1)]))),\n        testCase(\"tree/[5,100]/[insertLast(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [insertLast(1)]))),\n        testCase(\"tree/[500]/[removeFirst(1)]\", tree500, scuClone(treeTransform(tree500, [removeFirst(1)]))),\n        testCase(\"tree/[50,10]/[removeFirst(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [removeFirst(1)]))),\n        testCase(\"tree/[10,50]/[removeFirst(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [removeFirst(1)]))),\n        testCase(\"tree/[5,100]/[removeFirst(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [removeFirst(1)]))),\n        testCase(\"tree/[500]/[removeLast(1)]\", tree500, scuClone(treeTransform(tree500, [removeLast(1)]))),\n        testCase(\"tree/[50,10]/[removeLast(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [removeLast(1)]))),\n        testCase(\"tree/[10,50]/[removeLast(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [removeLast(1)]))),\n        testCase(\"tree/[5,100]/[removeLast(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [removeLast(1)]))),\n        testCase(\"tree/[500]/[moveFromEndToStart(1)]\", tree500, scuClone(treeTransform(tree500, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[50,10]/[moveFromEndToStart(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[10,50]/[moveFromEndToStart(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[5,100]/[moveFromEndToStart(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[500]/[moveFromStartToEnd(1)]\", tree500, scuClone(treeTransform(tree500, [moveFromStartToEnd(1)]))),\n        testCase(\"tree/[50,10]/[moveFromStartToEnd(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [moveFromStartToEnd(1)]))),\n        testCase(\"tree/[10,50]/[moveFromStartToEnd(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [moveFromStartToEnd(1)]))),\n        testCase(\"tree/[5,100]/[moveFromStartToEnd(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [moveFromStartToEnd(1)]))),\n        // special use case that should trigger worst case scenario for kivi library\n        testCase(\"tree/[500]/[kivi_worst_case]\", tree500, scuClone(treeTransform(treeTransform(treeTransform(tree500, [removeFirst(1)]), [removeLast(1)]), [reverse]))),\n        // special use case that should trigger worst case scenario for snabbdom library\n        testCase(\"tree/[500]/[snabbdom_worst_case]\", tree500, scuClone(treeTransform(tree500, [snabbdomWorstCase]))),\n        // special use case that should trigger worst case scenario for react library\n        testCase(\"tree/[500]/[react_worst_case]\", tree500, scuClone(treeTransform(treeTransform(treeTransform(tree500, [removeFirst(1)]), [removeLast(1)]), [moveFromEndToStart(1)]))),\n        // special use case that should trigger worst case scenario for virtual-dom library\n        testCase(\"tree/[500]/[virtual_dom_worst_case]\", tree500, scuClone(treeTransform(tree500, [moveFromStartToEnd(2)]))),\n        // test case with large amount of vnodes to test diff overhead\n        testCase(\"tree/[10,10,10,10]/no_change\", tree10__4, scuClone(tree10__4)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2,2,2]/no_change\", tree2__10, scuClone(tree2__10)),\n      ];\n    }\n  }\n  var macrotasks = [];\n  window.addEventListener(\"message\", function (e) {\n    if (e.source === window && e.data === \"uibench-macrotask\") {\n      var tasks = macrotasks;\n      macrotasks = [];\n      for (var i = 0; i < tasks.length; i++) {\n        tasks[i]();\n      }\n    }\n  });\n  function scheduleMacrotask(cb) {\n    if (macrotasks.length === 0) {\n      window.postMessage(\"uibench-macrotask\", \"*\");\n    }\n    macrotasks.push(cb);\n  }\n  var Executor = (function () {\n    function Executor(iterations, groups, onUpdate, onFinish, onProgress) {\n      var _this = this;\n      this._next = function () {\n        var group = _this.groups[_this._currentGroup];\n        if (_this._state === \"init\") {\n          if (config.timelineMarks) {\n            console.timeStamp(\"init \" + group.name);\n          }\n          _this.onUpdate(group.from, \"init\");\n          _this._state = \"update\";\n          if (memory.initial !== 0) {\n            memory.max = Math.max(memory.max, performance.memory.usedJSHeapSize);\n          }\n          requestAnimationFrame(_this._next);\n        }\n        else if (_this._state === \"update\") {\n          if (config.timelineMarks) {\n            console.timeStamp(\"update \" + group.name);\n          }\n          _this._startTime = window.performance.now();\n          _this.onUpdate(group.to, \"update\");\n          _this._state = \"measure_time\";\n          if (config.fullRenderTime) {\n            scheduleMacrotask(_this._next);\n          }\n          else {\n            _this._next();\n          }\n        }\n        else {\n          var t = window.performance.now() - _this._startTime;\n          if (config.timelineMarks) {\n            console.timeStamp(\"measure_time \" + group.name);\n          }\n          if (memory.start !== 0) {\n            memory.max = Math.max(memory.max, performance.memory.usedJSHeapSize);\n          }\n          _this.onProgress((_this._currentIteration * _this.groups.length + _this._currentGroup) / (_this.groups.length * _this.iterations));\n          var samples = _this._samples[group.name];\n          if (samples === undefined) {\n            samples = _this._samples[group.name] = [];\n          }\n          samples.push(t);\n          _this._state = \"init\";\n          _this._currentGroup++;\n          if (_this._currentGroup < _this.groups.length) {\n            requestAnimationFrame(_this._next);\n          }\n          else {\n            _this._currentIteration++;\n            if (_this._currentIteration < _this.iterations) {\n              _this._currentGroup = 0;\n              requestAnimationFrame(_this._next);\n            }\n            else {\n              _this.onFinish(_this._samples);\n              _this.onProgress(1);\n            }\n          }\n        }\n      };\n      this.iterations = iterations;\n      this.groups = groups;\n      this.onUpdate = onUpdate;\n      this.onFinish = onFinish;\n      this.onProgress = onProgress;\n      this._samples = {};\n      this._state = \"init\";\n      this._currentGroup = 0;\n      this._currentIteration = 0;\n      this._startTime = 0;\n    }\n    Executor.prototype.run = function () {\n      this._next();\n    };\n    return Executor;\n  }());\n  function firstRenderTime(onUpdate, done) {\n    var state = new AppState(\"table\", new HomeState(), config.mobile ? TableState.create(30, 4) : TableState.create(100, 4), AnimState.create(0), TreeState.create([0]));\n    var t = performance.now();\n    onUpdate(state, \"init\");\n    function finish() {\n      timing.firstRender = performance.now() - t;\n      done();\n    }\n    if (config.fullRenderTime) {\n      scheduleMacrotask(finish);\n    }\n    else {\n      finish();\n    }\n  }\n  function run(onUpdate, onFinish, filter) {\n    timing.run = performance.now();\n    if (memory.initial !== 0) {\n      memory.start = performance.memory.usedJSHeapSize;\n    }\n    firstRenderTime(onUpdate, function () {\n      if (!config.disableChecks) {\n        specTest(onUpdate);\n      }\n      scuTest(onUpdate, function (scuSupported) {\n        recyclingTest(onUpdate, function (recyclingEnabled) {\n          preserveStateTest(onUpdate, function (preserveState) {\n            initTests();\n            var tests = config.tests;\n            var name = config.name;\n            filter = filter || config.filter;\n            if (tests && filter) {\n              tests = tests.filter(function (t) { return t.name.indexOf(filter) !== -1; });\n            }\n            var progressBar = document.createElement(\"div\");\n            progressBar.className = \"ProgressBar\";\n            var progressBarInner = document.createElement(\"div\");\n            progressBarInner.className = \"ProgressBar_inner\";\n            progressBarInner.style.width = \"0\";\n            document.body.appendChild(progressBar);\n            progressBar.appendChild(progressBarInner);\n            function run() {\n              var e = new Executor(config.iterations, tests, onUpdate, function (samples) {\n                onFinish(samples);\n                if (config.report) {\n                  window.opener.postMessage({\n                    \"type\": \"report\",\n                    \"data\": {\n                      \"name\": name,\n                      \"version\": config.version,\n                      \"flags\": {\n                        \"fullRenderTime\": config.fullRenderTime,\n                        \"preserveState\": preserveState,\n                        \"scu\": scuSupported && !config.disableSCU,\n                        \"recycling\": recyclingEnabled,\n                        \"disableChecks\": config.disableChecks,\n                      },\n                      \"timing\": timing,\n                      \"memory\": memory,\n                      \"iterations\": config.iterations,\n                      \"samples\": samples,\n                    },\n                  }, \"*\");\n                }\n              }, function (progress) {\n                progressBarInner.style.width = Math.round(progress * 100) + \"%\";\n              });\n              e.run();\n            }\n            if (tests) {\n              if (config.startDelay > 0) {\n                setTimeout(run, config.startDelay);\n              }\n              else {\n                run();\n              }\n            }\n            else {\n              onFinish({});\n            }\n          });\n        });\n      });\n    });\n  }\n  timing.start = performance.now();\n\n  exports.config = config;\n  exports.init = init;\n  exports.run = run;\n  exports.TestCase = TestCase;\n\n}));\n"
  },
  {
    "path": "docs/uibench/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <link href=\"https://localvoid.github.io/uibench-base/0.1.0/styles.css\" rel=\"stylesheet\" />\n    <title>UI Benchmark: Inferno</title>\n</head>\n<body>\n<div id=\"App\"></div>\n<script src=\"https://localvoid.github.io/uibench-base/0.1.0/uibench.js\"></script>\n<script src=\"dist/bundle.js\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/uibench-inferno-compat/app.js",
    "content": "import { createTextVNode, linkEvent, render, version } from 'inferno-compat';\n\n/*\n * Inferno + inferno-compat without any Inferno specific optimizations\n * Optimization flags could be used, but the purpose is to track performance of slow code paths\n */\n\nuibench.init('Inferno compat (simple)', version);\n\nfunction TreeLeaf({ children }) {\n  return <li className=\"TreeLeaf\">{createTextVNode(children)}</li>;\n}\n\nfunction shouldDataUpdate(lastProps, nextProps) {\n  return lastProps !== nextProps;\n}\n\nfunction TreeNode({ data }) {\n  var length = data.children.length;\n  var children = new Array(length);\n\n  for (var i = 0; i < length; i++) {\n    var n = data.children[i];\n    var id = n.id;\n\n    if (n.container) {\n      children[i] = <TreeNode onComponentShouldUpdate={shouldDataUpdate} data={n} key={id} />;\n    } else {\n      children[i] = (\n        <TreeLeaf onComponentShouldUpdate={shouldDataUpdate} key={id}>\n          {id}\n        </TreeLeaf>\n      );\n    }\n  }\n\n  return <ul className=\"TreeNode\">{children}</ul>;\n}\n\nfunction tree(data) {\n  return (\n    <div className=\"Tree\">\n      <TreeNode data={data.root} onComponentShouldUpdate={shouldDataUpdate} />\n    </div>\n  );\n}\n\nfunction AnimBox({ data }) {\n  var time = data.time % 10;\n  var style = 'border-radius:' + time + 'px;' + 'background:rgba(0,0,0,' + (0.5 + time / 10) + ')';\n\n  return <div data-id={data.id} style={style} className=\"AnimBox\" />;\n}\n\nfunction anim(data) {\n  var items = data.items;\n  var length = items.length;\n  var children = new Array(length);\n\n  for (var i = 0; i < length; i++) {\n    var item = items[i];\n\n    // Here we are using onComponentShouldUpdate functional Component hook, to short circuit rendering process of AnimBox Component\n    // When the data does not change\n    children[i] = <AnimBox data={item} onComponentShouldUpdate={shouldDataUpdate} key={item.id} />;\n  }\n\n  return <div className=\"Anim\">{children}</div>;\n}\n\nfunction onClick(text, e) {\n  console.log('Clicked', text);\n  e.stopPropagation();\n}\n\nfunction TableCell({ children }) {\n  return (\n    <td onClick={linkEvent(children, onClick)} className=\"TableCell\">\n      {createTextVNode(children)}\n    </td>\n  );\n}\n\nfunction TableRow({ data }) {\n  var classes = 'TableRow';\n\n  if (data.active) {\n    classes = 'TableRow active';\n  }\n  var cells = data.props;\n  var length = cells.length + 1;\n  var children = new Array(length);\n\n  children[0] = <TableCell onComponentShouldUpdate={shouldDataUpdate}>{'#' + data.id}</TableCell>;\n\n  for (var i = 1; i < length; i++) {\n    children[i] = <TableCell onComponentShouldUpdate={shouldDataUpdate}>{cells[i - 1]}</TableCell>;\n  }\n\n  return (\n    <tr data-id={data.id} className={classes}>\n      {children}\n    </tr>\n  );\n}\n\nfunction table(data) {\n  var items = data.items;\n  var length = items.length;\n  var children = new Array(length);\n\n  for (var i = 0; i < length; i++) {\n    var item = items[i];\n\n    children[i] = (\n      <TableRow data={item} onComponentShouldUpdate={shouldDataUpdate} key={item.id}>\n        {item}\n      </TableRow>\n    );\n  }\n\n  return <table className=\"Table\">{children}</table>;\n}\n\nvar lastMainData;\n\nfunction main(data) {\n  lastMainData = data;\n  var location = data.location;\n  var section;\n\n  if (location === 'table') {\n    section = table(data.table);\n  } else if (location === 'anim') {\n    section = anim(data.anim);\n  } else if (location === 'tree') {\n    section = tree(data.tree);\n  }\n\n  return <div className=\"Main\">{section}</div>;\n}\n\ndocument.addEventListener('DOMContentLoaded', function (e) {\n  var container = document.querySelector('#App');\n\n  uibench.run(\n    function (state) {\n      render(main(state), container);\n    },\n    function (samples) {\n      render(<pre>{JSON.stringify(samples, null, ' ')}</pre>, container);\n    }\n  );\n});\n"
  },
  {
    "path": "docs/uibench-inferno-compat/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <link href=\"https://localvoid.github.io/uibench-base/0.1.0/styles.css\" rel=\"stylesheet\" />\n    <title>UI Benchmark: Inferno</title>\n</head>\n<body>\n<div id=\"App\"></div>\n<script src=\"https://localvoid.github.io/uibench-base/0.1.0/uibench.js\"></script>\n<script src=\"dist/bundle.js\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/uibench-lifecycle/app.js",
    "content": "import { version, Component, render, linkEvent } from 'inferno';\n\nuibench.init('Inferno [lifecycle overhead]', version);\n\nlet counter = 0;\n\nfunction onComponentWillMountCounter() {\n  counter++;\n}\n\nfunction onComponentDidMountCounter() {\n  counter++;\n}\n\nfunction onComponentShouldUpdateCounter() {\n  counter++;\n  return true;\n}\n\nfunction onComponentWillUpdateCounter() {\n  counter++;\n}\n\nfunction onComponentDidUpdateCounter() {\n  counter++;\n}\n\nfunction onComponentWillUnmountCounter() {\n  counter++;\n}\n\nfunction onComponentDidAppearCounter() {\n  counter++;\n}\n\nfunction onComponentWillDisappearCounter(dom, props, callback) {\n  counter++;\n  callback();\n}\n\nfunction onClick(text, e) {\n  console.log('Clicked', text);\n  e.stopPropagation();\n}\n\nfunction TableCell({ children }) {\n  return (\n    <td $HasTextChildren onClick={linkEvent(children, onClick)} className=\"TableCell\">\n      {children}\n    </td>\n  );\n}\n\nclass TableRow extends Component {\n  componentDidMount() {\n    counter++;\n  }\n\n  componentWillMount() {\n    counter++;\n  }\n\n  componentWillReceiveProps() {\n    counter++;\n  }\n\n  shouldComponentUpdate(nextProps, nextState) {\n    counter++;\n\n    return this.props.data !== nextProps.data;\n  }\n\n  componentDidUpdate() {\n    counter++;\n  }\n\n  componentWillUnmount() {\n    counter++;\n  }\n\n  componentDidAppear() {\n    counter++;\n  }\n\n  componentWillDisappear(dom, callback) {\n    counter++;\n    callback()\n  }\n\n  render() {\n    const { data } = this.props;\n\n    // Interned strings\n    const classes = data.active ? 'TableRow active' : 'TableRow';\n\n    const cells = data.props;\n\n    const children = [\n      <TableCell\n        onComponentWillMount={onComponentWillMountCounter}\n        onComponentDidMount={onComponentDidMountCounter}\n        onComponentShouldUpdate={onComponentShouldUpdateCounter}\n        onComponentWillUpdate={onComponentWillUpdateCounter}\n        onComponentDidUpdate={onComponentDidUpdateCounter}\n        onComponentWillUnmount={onComponentWillUnmountCounter}\n        onComponentDidAppear={onComponentDidAppearCounter}\n        onComponentWillDisappear={onComponentWillDisappearCounter}\n        key={-1}\n      >\n        {'#' + data.id}\n      </TableCell>\n    ];\n    for (let i = 0; i < cells.length; i++) {\n      // Key is used because React prints warnings that there should be a key, libraries that can detect that children\n      // shape isn't changing should render cells without keys.\n      children.push(\n        <TableCell\n          onComponentWillMount={onComponentWillMountCounter}\n          onComponentDidMount={onComponentDidMountCounter}\n          onComponentShouldUpdate={onComponentShouldUpdateCounter}\n          onComponentWillUpdate={onComponentWillUpdateCounter}\n          onComponentDidUpdate={onComponentDidUpdateCounter}\n          onComponentWillUnmount={onComponentWillUnmountCounter}\n          onComponentDidAppear={onComponentDidAppearCounter}\n          onComponentWillDisappear={onComponentWillDisappearCounter}\n          key={i}\n        >\n          {cells[i]}\n        </TableCell>);\n    }\n\n    // First table cell is inserted this way to prevent react from printing warning that it doesn't have key property\n    return (\n      <tr className={classes} data-id={data.id}>\n        {children}\n      </tr>\n    );\n  }\n}\n\nclass Table extends Component {\n  componentDidMount() {\n    counter++;\n  }\n\n  componentWillMount() {\n    counter++;\n  }\n\n  componentWillReceiveProps() {\n    counter++;\n  }\n\n  shouldComponentUpdate(nextProps, nextState) {\n    counter++;\n\n    return this.props.data !== nextProps.data;\n  }\n\n  componentDidUpdate() {\n    counter++;\n  }\n\n  componentWillUnmount() {\n    counter++;\n  }\n\n  componentDidAppear() {\n    counter++;\n  }\n\n  componentWillDisappear(dom, callback) {\n    counter++;\n    callback()\n  }\n\n  render() {\n    const items = this.props.data.items;\n\n    const children = [];\n    for (let i = 0; i < items.length; i++) {\n      const item = items[i];\n      children.push(<TableRow key={item.id} data={item} />);\n    }\n\n    return (\n      <table className=\"Table\">\n        <tbody>{children}</tbody>\n      </table>\n    );\n  }\n}\n\nfunction AnimBox({ data }) {\n  var time = data.time % 10;\n  var style = 'border-radius:' + time + 'px;' + 'background:rgba(0,0,0,' + (0.5 + time / 10) + ')';\n\n  return <div data-id={data.id} style={style} className=\"AnimBox\" />;\n}\n\n\nclass Anim extends Component {\n  componentDidMount() {\n    counter++;\n  }\n\n  componentWillMount() {\n    counter++;\n  }\n\n  componentWillReceiveProps() {\n    counter++;\n  }\n\n  shouldComponentUpdate(nextProps, nextState) {\n    counter++;\n\n    return this.props.data !== nextProps.data;\n  }\n\n  componentDidUpdate() {\n    counter++;\n  }\n\n  componentWillUnmount() {\n    counter++;\n  }\n\n  componentDidAppear() {\n    counter++;\n  }\n\n  componentWillDisappear(dom, callback) {\n    counter++;\n    callback()\n  }\n\n  render() {\n    const items = this.props.data.items;\n\n    const children = [];\n    for (let i = 0; i < items.length; i++) {\n      const item = items[i];\n      children.push(<AnimBox\n        onComponentWillMount={onComponentWillMountCounter}\n        onComponentDidMount={onComponentDidMountCounter}\n        onComponentShouldUpdate={onComponentShouldUpdateCounter}\n        onComponentWillUpdate={onComponentWillUpdateCounter}\n        onComponentDidUpdate={onComponentDidUpdateCounter}\n        onComponentWillUnmount={onComponentWillUnmountCounter}\n        onComponentDidAppear={onComponentDidAppearCounter}\n        onComponentWillDisappear={onComponentWillDisappearCounter}\n        key={item.id}\n        data={item}\n      />);\n    }\n\n    return <div className=\"Anim\">{children}</div>;\n  }\n}\n\nfunction TreeLeaf({ children }) {\n  return (\n    <li $HasTextChildren className=\"TreeLeaf\">\n      {children}\n    </li>\n  );\n}\n\nclass TreeNode extends Component {\n  componentDidMount() {\n    counter++;\n  }\n\n  componentWillMount() {\n    counter++;\n  }\n\n  componentWillReceiveProps() {\n    counter++;\n  }\n\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  componentDidUpdate() {\n    counter++;\n  }\n\n  componentWillUnmount() {\n    counter++;\n  }\n\n  componentDidAppear() {\n    counter++;\n  }\n\n  componentWillDisappear(dom, callback) {\n    counter++;\n    callback()\n  }\n\n  render() {\n    const { data } = this.props;\n    const children = [];\n\n    for (let i = 0; i < data.children.length; i++) {\n      const n = data.children[i];\n      const id = n.id;\n\n      if (n.container) {\n        children.push(<TreeNode key={id} data={n} />);\n      } else {\n        children.push(<TreeLeaf\n          onComponentWillMount={onComponentWillMountCounter}\n          onComponentDidMount={onComponentDidMountCounter}\n          onComponentShouldUpdate={onComponentShouldUpdateCounter}\n          onComponentWillUpdate={onComponentWillUpdateCounter}\n          onComponentDidUpdate={onComponentDidUpdateCounter}\n          onComponentWillUnmount={onComponentWillUnmountCounter}\n          onComponentDidAppear={onComponentDidAppearCounter}\n          onComponentWillDisappear={onComponentWillDisappearCounter}\n          key={id}\n        >\n          {id}\n        </TreeLeaf>);\n      }\n    }\n\n    return <ul className=\"TreeNode\">{children}</ul>;\n  }\n}\n\nclass Tree extends Component {\n\n  componentDidMount() {\n    counter++;\n  }\n\n  componentWillMount() {\n    counter++;\n  }\n\n  componentWillReceiveProps() {\n    counter++;\n  }\n\n  shouldComponentUpdate(nextProps, nextState) {\n    counter++;\n\n    return this.props.data !== nextProps.data;\n  }\n\n  componentDidUpdate() {\n    counter++;\n  }\n\n  componentWillUnmount() {\n    counter++;\n  }\n\n  componentDidAppear() {\n    counter++;\n  }\n\n  componentWillDisappear(dom, callback) {\n    counter++;\n    callback()\n  }\n\n  render() {\n    return (\n      <div className=\"Tree\">\n        <TreeNode data={this.props.data.root} />\n      </div>\n    );\n  }\n}\n\nclass Main extends Component {\n  componentDidMount() {\n    counter++;\n  }\n\n  componentWillMount() {\n    counter++;\n  }\n\n  componentWillReceiveProps() {\n    counter++;\n  }\n\n  shouldComponentUpdate(nextProps, nextState) {\n    counter++;\n\n    return this.props.data !== nextProps.data;\n  }\n\n  componentDidUpdate() {\n    counter++;\n  }\n\n  componentWillUnmount() {\n    counter++;\n  }\n\n  componentDidAppear() {\n    counter++;\n  }\n\n  componentWillDisappear(dom, callback) {\n    counter++;\n    callback()\n  }\n\n  render() {\n    const { data } = this.props;\n    const location = data.location;\n\n    var section;\n    if (location === 'table') {\n      section = <Table data={data.table}></Table>;\n    } else if (location === 'anim') {\n      section = <Anim data={data.anim}></Anim>;\n    } else if (location === 'tree') {\n      section = <Tree data={data.tree}></Tree>;\n    }\n\n    return <div className=\"Main\">{section}</div>;\n  }\n}\n\ndocument.addEventListener('DOMContentLoaded', function (e) {\n  var container = document.querySelector('#App');\n\n  uibench.run(\n    function (state) {\n      render(<Main data={state} />, container);\n    },\n    function (samples) {\n      // console log the counter to avoid the variable being removed by JIT\n      console.log(counter);\n      render(<pre>{JSON.stringify(samples, null, ' ')}</pre>, container);\n    }\n  );\n});\n"
  },
  {
    "path": "docs/uibench-lifecycle/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <link href=\"https://localvoid.github.io/uibench-base/0.1.0/styles.css\" rel=\"stylesheet\" />\n    <title>UI Benchmark: Inferno lifecycle</title>\n</head>\n<body>\n<div id=\"App\"></div>\n<script src=\"https://localvoid.github.io/uibench-base/0.1.0/uibench.js\"></script>\n<script src=\"dist/bundle.js\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/uibench-normalization/app.js",
    "content": "import { linkEvent, render, version } from 'inferno';\n\n/*\n * The purpose of this benchmark is to test performance regressions in normalization process.\n * This benchmark is slow intentionally. There are nested arrays and other \"bad code\".\n */\n\nuibench.init('Inferno (normalization test)', version);\n\nfunction TreeLeaf({ children }) {\n  return <li className=\"TreeLeaf\">{children}</li>;\n}\n\nfunction shouldDataUpdate(lastProps, nextProps) {\n  return lastProps !== nextProps;\n}\n\nfunction TreeNode({ data }) {\n  var length = data.children.length;\n  var children = new Array(length);\n\n  for (var i = 0; i < length; i++) {\n    var n = data.children[i];\n    var id = n.id;\n\n    if (n.container) {\n      children[i] = <TreeNode onComponentShouldUpdate={shouldDataUpdate} data={n} key={id} />;\n    } else {\n      children[i] = (\n        <TreeLeaf onComponentShouldUpdate={shouldDataUpdate} key={id}>\n          {id}\n        </TreeLeaf>\n      );\n    }\n  }\n\n  return <ul className=\"TreeNode\">{children}</ul>;\n}\n\nfunction tree(data) {\n  return (\n    <div className=\"Tree\">\n      <TreeNode data={data.root} onComponentShouldUpdate={shouldDataUpdate} />\n    </div>\n  );\n}\n\nfunction AnimBox({ data }) {\n  var time = data.time % 10;\n  var style = 'border-radius:' + time + 'px;' + 'background:rgba(0,0,0,' + (0.5 + time / 10) + ')';\n\n  return <div data-id={data.id} style={style} className=\"AnimBox\" />;\n}\n\nfunction anim(data) {\n  var items = data.items;\n  var length = items.length;\n  var children = new Array(length);\n\n  for (var i = 0; i < length; i++) {\n    var item = items[i];\n\n    // Here we are using onComponentShouldUpdate functional Component hook, to short circuit rendering process of AnimBox Component\n    // When the data does not change\n    children[i] = <AnimBox data={item} onComponentShouldUpdate={shouldDataUpdate} key={item.id} />;\n  }\n\n  return <div className=\"Anim\">{children}</div>;\n}\n\nfunction onClick(text, e) {\n  console.log('Clicked', text);\n  e.stopPropagation();\n}\n\nfunction TableCell({ children }) {\n  /*\n   * The carbage code is intentional\n   */\n  return (\n    <td onClick={linkEvent(children, onClick)} className=\"TableCell\">\n      {null}\n      {false}\n      {[children]}\n    </td>\n  );\n}\n\nfunction TableRow({ data }) {\n  var classes = 'TableRow';\n\n  if (data.active) {\n    classes = 'TableRow active';\n  }\n  var cells = data.props;\n  var length = cells.length + 1;\n  var children = new Array(length);\n\n  children[0] = <TableCell onComponentShouldUpdate={shouldDataUpdate}>{'#' + data.id}</TableCell>;\n\n  for (var i = 1; i < length; i++) {\n    children[i] = <TableCell onComponentShouldUpdate={shouldDataUpdate}>{cells[i - 1]}</TableCell>;\n  }\n\n  /*\n   * The carbage code is intentional\n   */\n  return (\n    <tr data-id={data.id} className={classes}>\n      {null}\n      {children}\n      {false}\n    </tr>\n  );\n}\n\nfunction table(data) {\n  var items = data.items;\n  var length = items.length;\n  var children = new Array(length);\n\n  for (var i = 0; i < length; i++) {\n    var item = items[i];\n\n    children[i] = (\n      <TableRow data={item} onComponentShouldUpdate={shouldDataUpdate} key={item.id}>\n        {item}\n      </TableRow>\n    );\n  }\n\n  /*\n   * The carbage code is intentional\n   */\n  return (\n    <table className=\"Table\">\n      {[]}\n      {children}\n      {[[]]}\n    </table>\n  );\n}\n\nvar lastMainData;\n\nfunction main(data) {\n  lastMainData = data;\n  var location = data.location;\n  var section;\n\n  if (location === 'table') {\n    section = table(data.table);\n  } else if (location === 'anim') {\n    section = anim(data.anim);\n  } else if (location === 'tree') {\n    section = tree(data.tree);\n  }\n\n  return <div className=\"Main\">{section}</div>;\n}\n\ndocument.addEventListener('DOMContentLoaded', function (e) {\n  var container = document.querySelector('#App');\n\n  uibench.run(\n    function (state) {\n      render(main(state), container);\n    },\n    function (samples) {\n      render(<pre>{JSON.stringify(samples, null, ' ')}</pre>, container);\n    }\n  );\n});\n"
  },
  {
    "path": "docs/uibench-normalization/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <link href=\"https://localvoid.github.io/uibench-base/0.1.0/styles.css\" rel=\"stylesheet\" />\n    <title>UI Benchmark: Inferno</title>\n</head>\n<body>\n<div id=\"App\"></div>\n<script src=\"https://localvoid.github.io/uibench-base/0.1.0/uibench.js\"></script>\n<script src=\"dist/bundle.js\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/uibench-reactlike/app.js",
    "content": "import { version, Component, render } from 'inferno';\n\nuibench.init('Inferno [same as react]', version);\n\nclass TableCell extends Component {\n  constructor(props) {\n    super(props);\n    this.onClick = this.onClick.bind(this);\n  }\n\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.text !== nextProps.text;\n  }\n\n  onClick(e) {\n    console.log('Clicked' + this.props.text);\n    e.stopPropagation();\n  }\n\n  render() {\n    return (\n      <td className=\"TableCell\" onClick={this.onClick}>\n        {this.props.text}\n      </td>\n    );\n  }\n}\n\nclass TableRow extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const { data } = this.props;\n\n    // Interned strings\n    const classes = data.active ? 'TableRow active' : 'TableRow';\n\n    const cells = data.props;\n\n    const children = [<TableCell key={-1} text={'#' + data.id}></TableCell>];\n    for (let i = 0; i < cells.length; i++) {\n      // Key is used because React prints warnings that there should be a key, libraries that can detect that children\n      // shape isn't changing should render cells without keys.\n      children.push(<TableCell key={i} text={cells[i]}></TableCell>);\n    }\n\n    // First table cell is inserted this way to prevent react from printing warning that it doesn't have key property\n    return (\n      <tr className={classes} data-id={data.id}>\n        {children}\n      </tr>\n    );\n  }\n}\n\nclass Table extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const items = this.props.data.items;\n\n    const children = [];\n    for (let i = 0; i < items.length; i++) {\n      const item = items[i];\n      children.push(<TableRow key={item.id} data={item} />);\n    }\n\n    return (\n      <table className=\"Table\">\n        <tbody>{children}</tbody>\n      </table>\n    );\n  }\n}\n\nclass AnimBox extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const { data } = this.props;\n    const time = data.time;\n    const style = {\n      'border-radius': (time % 10).toString() + 'px',\n      background: 'rgba(0,0,0,' + (0.5 + (time % 10) / 10).toString() + ')'\n    };\n\n    return <div className=\"AnimBox\" data-id={data.id} style={style} />;\n  }\n}\n\nclass Anim extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const items = this.props.data.items;\n\n    const children = [];\n    for (let i = 0; i < items.length; i++) {\n      const item = items[i];\n      children.push(<AnimBox key={item.id} data={item} />);\n    }\n\n    return <div className=\"Anim\">{children}</div>;\n  }\n}\n\nclass TreeLeaf extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    return <li className=\"TreeLeaf\">{this.props.data.id}</li>;\n  }\n}\n\nclass TreeNode extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const { data } = this.props;\n    const children = [];\n\n    for (let i = 0; i < data.children.length; i++) {\n      const n = data.children[i];\n      if (n.container) {\n        children.push(<TreeNode key={n.id} data={n} />);\n      } else {\n        children.push(<TreeLeaf key={n.id} data={n} />);\n      }\n    }\n\n    return <ul className=\"TreeNode\">{children}</ul>;\n  }\n}\n\nclass Tree extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    return (\n      <div className=\"Tree\">\n        <TreeNode data={this.props.data.root} />\n      </div>\n    );\n  }\n}\n\nclass Main extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const { data } = this.props;\n    const location = data.location;\n\n    var section;\n    if (location === 'table') {\n      section = <Table data={data.table}></Table>;\n    } else if (location === 'anim') {\n      section = <Anim data={data.anim}></Anim>;\n    } else if (location === 'tree') {\n      section = <Tree data={data.tree}></Tree>;\n    }\n\n    return <div className=\"Main\">{section}</div>;\n  }\n}\n\ndocument.addEventListener('DOMContentLoaded', function (e) {\n  var container = document.querySelector('#App');\n\n  uibench.run(\n    function (state) {\n      render(<Main data={state} />, container);\n    },\n    function (samples) {\n      render(<pre>{JSON.stringify(samples, null, ' ')}</pre>, container);\n    }\n  );\n});\n"
  },
  {
    "path": "docs/uibench-reactlike/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <link href=\"https://localvoid.github.io/uibench-base/0.1.0/styles.css\" rel=\"stylesheet\" />\n    <title>UI Benchmark: Inferno</title>\n</head>\n<body>\n<div id=\"App\"></div>\n<script src=\"https://localvoid.github.io/uibench-base/0.1.0/uibench.js\"></script>\n<script src=\"dist/bundle.js\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "documentation/v4-migration.md",
    "content": "#### V4 Breaking changes:\n\n`inferno-component` is removed. Inferno.Component (ES6) Class has been moved to `inferno` package.\n\n`findDOMNode` has been moved to `inferno-compat`\n\nstring components now require `inferno-compat`\n\nDefault exports have been removed from all packages except `inferno-compat`. If you are getting exception for example:\ncannot read `Inferno.createComponentVNode` make sure you have babel-plugin-inferno before babel module transformers in your `.babelrc` file.\n\nInferno packages are now using peerDependencies to external components to avoid duplicates\n\n`module` entry has been added to package.json for all packages.\n\n**NOTE:** module entry point (`\"module\": \"index.mjs\"`) targets to production build of Inferno. If you are doing development using Inferno you should use `dist/index.dev.js` - file or module entry point: `\"dev:module\": \"dist/index.dev.mjs\"`\n\n`createVNode` cannot be used to create Component vNodes anymore. use `createComponentVNode(flags, type, props, key, ref)` instead.\n\nVNodeFlags and ChildrenFlags have changed, see inferno-vnode-flags package for new flags.\n\nThere is no more \"noNormalize\" parameter for `createVNode` if you have been using it and you need to normalize children you need to pass `childFlags.UnknownChildren` as childFlags parameter.\n\nexample:\n```javascript\nimport {createVNode, render} from 'inferno';\nimport {VNodeFlags, ChildFlags} from 'inferno-vnode-flags';\n\nrender(\n    createVNode(\n        VNodeFlags.HtmlElement,\n        'div',\n        'example-class'\n        data, // unknown children\n        ChildFlags.UnknownChildren // This tells inferno to normalize (data)\n    ),\n    document.getElementById('root')\n);\n```\n\ninferno-compat users should install all dependencies they use themselves. For example:\n\n```bash\nnpm install --save inferno\nnpm install --save inferno-compat\nnpm install --save inferno-clone-vnode\nnpm install --save inferno-create-class\nnpm install --save inferno-create-element\n```\n\n- Many JSX flags have changed, see babel-plugin-inferno README for more information\n\n\n### Create Inferno App\n\nIt now uses `npx create-inferno-app your-app` to create new application\n"
  },
  {
    "path": "documentation/v6-migration.md",
    "content": "#### V6 Breaking changes:\n\n## Hydration, re-using SSR on client side\n\n> Shortly:\n>\n> `hydrate` moved to `inferno-hydrate` package\n>\n\n\nNot all applications need server side rendering, so hydration functionality has been moved to `inferno-hydrate` package.\nInferno render will no longer try to re-use server side rendered HTML automatically.\nIf you want to hydrate (render existing html) you need to install `inferno-hydrate` package\nand call hydrate on first render.\n\n```jsx\nimport { render } from 'inferno';\nimport { hydrate } from 'inferno-hydrate';\n\n// First time client is loaded, FE:\n\ndocument.addEventListener('DOMContentLoaded', function(e) {\n    const element = document.getElementById('app');\n\n    hydrate(<App data={initialData} />, element);\n\n    // Future updates should use render\n    render(<App data={newData} />, element);\n});\n```\n\n## Style property names changed\n\n> Shortly:\n>\n> `backgroundColor` becomes `background-color`\n>\n> `top: 10` becomes `top: \"10px\"`\n>\n\nTo support the latest style API inferno needs to set styles using `dom.style.setProperty()`.\nThis change adds support for inline CSS variables and if browser vendors add new parameters its easier to extend.\n\nThere used to be a list of hardcoded properties which Inferno detected and automatically added `px` suffix to, when value was numeric.\nInferno will no longer get between application input and setting style property. When you set `top: 1` you get `<div style=\"top: 1\"></div>`\n\nUnlike React, inferno has always supported setting styles using string. This API is now unified with object literal API.\nIt supports the same features and uses the same syntax.\n\n```jsx\n<div style=\"background-color: green; top: 10;\"></div>\n// equals\n<div style={{\"background-color\": \"green\", top: 10}}></div>\n```\n\n`inferno-compat` still uses the same old way and transpiles property names runtime to InfernoJS equivalents.\nIf you don't need camelCase styles you can disable this runtime using Inferno.options API.\n\n```jsx\nimport {options} from 'inferno-compat';\n\n// Disabling reactStyles uses native CSS syntax\noptions.reactStyles = false;\n```\n\n## JSX plugin requires Babel 7\n\nTo support JSX Fragment syntax, [babel-plugin-inferno](https://github.com/infernojs/babel-plugin-inferno) now depends on\n[babel v7](https://babeljs.io/blog/2018/08/27/7.0.0).\n\n## Lifecycle changes\n\n`setState` lifecycle has been changed to be compatible with ReactJS flow.\nAlso `componentDidUpdate` will now trigger later in lifecycle chain, after refs have been creted.\nSee: https://github.com/infernojs/inferno/issues/1286\n\n\n## Changes in VNode properties\n\n#### `dom` not always populated\n\nSupporting fragments complicates vNode structure and `dom` property is no longer populated\nto Components or Fragments. There is [inferno-extras](https://github.com/infernojs/inferno/tree/master/packages/inferno-extras) package which contains helper functions to get DOM node.\n\n```jsx\nimport { Component } from 'inferno';\nimport { findDOMNode } from 'inferno-extras';\n\nclass Example extends Component {\n\n    componentDidMount() {\n        // element equals \"<div>Okay</div>\"\n        const element = findDOMNode(this);\n    }\n\n    render() {\n        return <div>Okay</div>;\n    }\n}\n\n```\n\n#### `parentVNode` removed\n\nThere used to be reference to `parentVNode` from Component vNodes due to technical difficulties of changing Component roots.\nThis issue has been now resolved and `parentVNode` references have been removed.\n\n\n#### single textVNodes are no longer inside another VNode\n\nIn Inferno v5 vNode elements that had text children had the following structure.\nV6 adds new optimization paths for text children.\n\n```jsx\nconst vNode = <div>Hello</div>\n\n// children property now holds the string\nvNode.children === 'Hello';\n```\n\n## Component properties removed\n\nAll Component properties which start with `$` are considered private and their behavior can change in minor versions.\n\n- `$V` has been removed. no work around available.\n- `$P` has been removed. use `findDOMNode(this).parentNode`\n\n\n## Inferno-server\n\nInferno server no longer adds comment tags to separate single text children.\nMake sure client and server use the same version SSR v6 needs client v6.\n\n## Legacy String refs removed\n\nInferno no longer supports legacy string refs at all. They are not supported through `inferno-compat` either.\nYou can use callback refs, createRef API or forward Refs.\n"
  },
  {
    "path": "documentation/v6-release.md",
    "content": "# InfernoJS v6.0.0\n\n## Breaking changes\n\n- `hydrate` moved to `inferno-hydrate` package\n- Style properties use hyphen syntax `backgroundColor` => `background-color`\n- JSX plugin depends on babel v7\n- Lifecycle changed to have better compatibility with ReactJS\n- String refs completely removed\n\n\nFor complete list see [Migration guide](https://github.com/infernojs/inferno/blob/master/documentation/v6-migration.md)\n\n## New features\n\n- Fragments, a new type of VNode that can be used to render Component root level arrays\n- createRef API\n- forwardRef API\n- new Component lifecycle: `getDerivedStateFromProps` and `getSnapshotBeforeUpdate`\n- `$HasTextChildren` new JSX compilation time optimization flag added\n- rerender method\n- top level context\n\n\n\n### Fragments\n\nFragment support means you can return array from Component render creating an invisible layer that ties its content together\nbut will not render any container to actual DOM. The examples below need v6 [babel-plugin-inferno](https://github.com/infernojs/babel-plugin-inferno)\n\nShort syntax example `<> ... </>`\n\n```jsx\nimport { Component } from 'inferno';\n\nclass MyApplication extends Component {\n\n    render() {\n\n        /*\n         * This will render \"<span>Hi</span><div>Okay</div>\"\n         * to location where MyApplication is used\n         * /\n        return (\n            <>\n                <span>Hi</span>\n                <div>Okay</div>\n            </>\n        )\n    }\n}\n\n```\n\nLong syntax allows you to specify keys for Fragments. This is useful if there are many Fragments or if array is built dynamically.\n\n```jsx\nimport { Component, Fragment } from 'inferno';\n\nclass MyApplication extends Component {\n\n    render() {\n\n        const list = [];\n\n\n        if (/* some logic */) {\n            list.push(\n                <Fragment key=\"coffee\">\n                    <dt>Coffee</dt>\n                    <dd>Black hot drink</dd>\n                </Fragment/>\n            );\n        }\n\n        ...\n\n        if (/* other logic */) {\n            list.push(\n                <Fragment key=\"milk\">\n                    <dt>Milk</dt>\n                    <dd>White cold drink</dd>\n                </Fragment/>\n            );\n        }\n\n        /*\n         * This will render\n         * <dl>\n         *    <dt>Coffee</dt>\n         *    <dd>Black hot drink</dd>\n         *    <dt>Milk</dt>\n         *    <dd>White cold drink</dd>\n         * </dl>\n         * /\n        return (\n            <dl>\n                {list}\n            </dl>\n        )\n    }\n}\n\n```\n\nYou can create fragment:\n\n- Using native Inferno API `createFragment(children: any, childFlags: ChildFlags, key?: string | number | null)`\n- Using JSX `<> ... </>`, `<Fragment> .... </Fragment>` or `<Inferno.Fragment> ... </Inferno.Fragment>`\n- Using createElement API `createElement(Inferno.Fragment, {key: 'test'}, ...children)`\n- Using hyperscript API `h(Inferno.Fragment, {key: 'test'}, children)`\n\nReact documentation: https://reactjs.org/docs/fragments.html\n\n### CreateRef API\n\ncreateRef method allows nicer syntax, and reduces code when no callback to DOM creation is needed.\nThe below example creates ref object and stores it to Component property `element`.\nThis object is then assigned to the element where you want to create reference. In the example below we want to reference \"span\".\nAfter render has gone, span element is available in `this.element.current` property.\n\n\n```jsx\nimport { Component, render, createRef } from 'inferno';\n\nclass Foobar extends Component {\n  constructor(props) {\n    super(props);\n\n    // Store reference somewhere\n    this.element = createRef(); // Returns object {current: null}\n  }\n\n  render() {\n    return (\n      <div>\n        <span id=\"span\" ref={this.element}>\n          Ok\n        </span>\n      </div>\n    );\n  }\n}\n\nrender(<Foobar />, container);\n\n```\n\nReact documentation: https://reactjs.org/docs/refs-and-the-dom.html\n\n\n### ForwardRef API\n\nforwardRef is a new mechanism to \"forward\" ref inside a functional Component.\nIt can be useful if you have simple functional Components and you want to create reference to a specific element inside it.\n\n```jsx\nimport { forwardRef, Component, render } from 'inferno';\n\nconst FancyButton = forwardRef((props, ref) => (\n  <button ref={ref} className=\"FancyButton\">\n    {props.children}\n  </button>\n));\n\nclass Hello extends Component {\n  render() {\n    return (\n      <FancyButton\n        ref={btn => {\n          if (btn) {\n            // btn variable is the button rendered from FancyButton\n          }\n        }}\n      >\n        Click me!\n      </FancyButton>\n    );\n  }\n}\n\nrender(<Hello />, container);\n```\n\nReact documentation: https://reactjs.org/docs/forwarding-refs.html\n\n### New lifecycle\n\nLike in React when new lifecycle methods `getDerivedStateFromProps` or `getSnapshotBeforeUpdate` are used old lifecycle methods will not be called ( `componentWillMount`, `componentWillReceiveProps` `componentWillUpdate` ).\nThere will not be `UNSAFE_` methods in Inferno. Just use the normal names.\n\n\n### TextChildren\n\nNew optimization paths have been added for text. JSX users can force this optimization by adding `$HasTextChildren` tag to any vNode element.\nThis makes given element always render text. Normalization will also default into text children when only single text element is detected as children.\n\nThis flag also simplifies an old version of:\n```\nimport { createTextVNode } from 'inferno';\n\n// While this still works, this is not recommended anymore\n<div $HasVNodeChildren>{createTextVNode('text')}</div>\n```\n\nNew version:\n```\n// No imports needed\n<div $HasTextChildren>text</div>\n```\n\n\n### rerender\n\nrerender is a new method that will flush all pending setState calls and render immediately.\nIt can be used when render timing is important, or to simplify tests.\n\n```jsx\nimport { Component, rerender, render } from 'inferno';\n\ndescribe('test example', () => {\n    it('Should update immediately', () => {\n      class Foo extends Component {\n        constructor(props, context) {\n          super(props, context);\n\n          this.state = {\n            value: 'initial'\n          };\n        }\n\n        componentDidMount() {\n          this.setState({ value: 'updated' });\n        }\n\n        render() {\n          return <div className={this.state.value} />;\n        }\n      }\n\n      const container = document.createElement('div');\n\n      render(<Foo />, container);\n      expect(container.firstChild.className).toEqual('initial');\n\n      // Call rerender to flush pending setState, no timeouts needed\n      rerender();\n      expect(container.firstChild.className).toEqual('updated');\n    });\n});\n```\n\n### Top level context\n\nInferno.render now takes fourth parameter which is initial context.\nThis removes the need of wrapping application with Class component.\n\n```jsx\nimport { render } from 'inferno';\n\nfunction App (props, context) {\n    // context contains property \"foo\" => \"bar\"\n\n    return <div>Cool App!</div>;\n}\n\n\nrender(<App />, document.getElementById('root'), callback, { foo: 'bar' });\n```\n\n## Common\n\nRuntime memory usage has been improved. `dom` properties are no longer stored to component vNode.\nVarious properties have been removed from ES6 Component as well. `parentVNode` hack has been removed removing circular\nreferences from vNode tree. Normalization `array['$'] = true` hack has been removed.\n\n### Core\n\n- Better recovery from user land errors\n- Fixes performance issue where normalization copied input data two times\n- Fixes performance issue where frozen input data was always copied\n\n### Typescript\n\n- Adds support for pointer event types\n- setState typings have been improved. https://github.com/infernojs/inferno/pull/1388\n\n### Inferno-router\n\n- Improved nested routes handling #1360\n- `Route` component can now have multiple children\n\n### Inferno-compat\n\n- `options.reactStyles` option added, setting it false removes runtime transformation of style properties\n\n\nList of Github issues can be found using this link: https://github.com/infernojs/inferno/issues?utf8=%E2%9C%93&q=label%3A%22Fixed+in+v6.0.0%22+\n\n\n"
  },
  {
    "path": "documentation/v9-migration.md",
    "content": "# InfernoJS v9.0.0\n\n## Breaking changes\n\n`inferno-create-class` has been removed, use `createComponentVNode`, `createElement` APIs instead.\nIf you were using `createClass` to wrap the class into observable you can do the same by extending inferno component.\n\n```js\nobserver(\n  class MyCom extends Component {\n    componentWillReact() {\n      willReactCount++;\n    }\n\n    render() {\n      return (\n        <div id=\"x\">\n          {[foo.a.get(), foo.b.get(), foo.c.get()].join(',')}\n        </div>\n      );\n    }\n  },\n);\n```\n\nInferno v9 requires following features to be present in the executing runtime:\n\n- `Promise`\n- `String.prototype.includes()`\n- `String.prototype.startsWith()`\n- `Array.prototype.includes()`\n- `Object.spread()`\n\n`options.componentComparator` has been removed\n`options.renderComplete` has been removed, same result can be achieved by calling own function after render\n\n## ES module bundle extension is now `.mjs`\n\n`inferno.esnext.js` bundle has been removed and replaced with `inferno.mjs` bundle.\nThe following bundles have been renamed:\n\n`inferno.esm.js` is now `inferno.mjs`\n\n`inferno.dev.esm.js` is now `inferno.dev.mjs`\n"
  },
  {
    "path": "eslint.config.js",
    "content": "import globals from 'globals';\nimport eslint from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport importPlugin from 'eslint-plugin-import';\nimport eslintConfigPrettier from 'eslint-config-prettier'\nimport eslintInferno from 'eslint-plugin-inferno'\n\nexport default tseslint.config(\n    {\n        languageOptions: {\n            globals: {\n                ...globals.browser,\n                ...globals.node,\n                ...globals.jest,\n                ...globals.jasmine\n            }\n        }\n    },\n    {\n        ignores: [\"**/dist/*\", \"**/*.cjs\", \"**/*.min.js\"]\n    },\n    eslint.configs.recommended,\n    tseslint.configs.recommended,\n    importPlugin.flatConfigs.typescript,\n    eslintInferno.configs.flat.recommended,\n    eslintConfigPrettier,\n    {\n        rules: {\n            \"@typescript-eslint/no-unsafe-function-type\": \"off\",\n            \"@typescript-eslint/no-explicit-any\": \"off\",\n        }\n    },\n    {\n        // Specific rules for tests\n        files: [\"**/__tests__/**\"],\n        rules: {\n            \"@typescript-eslint/no-unused-vars\": \"off\",\n            \"@typescript-eslint/ban-ts-comment\": \"off\",\n            \"@typescript-eslint/no-this-alias\": \"off\",\n            \"prefer-rest-params\": \"off\",\n            \"inferno/jsx-key\": \"off\", // There are tests intentionally testing for missing keys\n            \"inferno/no-children-prop\": \"off\", // There are tests intentionally testing for children prop\n            \"inferno/no-unescaped-entities\": \"off\"\n        }\n    }\n)"
  },
  {
    "path": "fixtures/browser/gzip/gzippreprocessor.js",
    "content": "const zlib = require('zlib');\n\nconst bytesToSize = (bytes) => {\n  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n  if (bytes === 0) {\n    return '0 Byte';\n  }\n  const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10);\n  return Math.round(bytes / 1024 ** i, 2) + sizes[i];\n};\n\n// Preprocess files to provide a gzip compressed alternative version\nfunction Preprocessor(config, logger) {\n  const log = logger.create('preprocessor.gzip');\n\n  return (content, file, done) => {\n    const originalSize = content.length;\n    // const contentBuffer = Buffer.isBuffer(content) ? content : Buffer.from(content);\n\n    zlib.gzip(content, (err, gzippedContent) => {\n      if (err) {\n        log.error(err);\n        done(err);\n        return;\n      }\n\n      // eslint-disable-next-line no-param-reassign\n      file.encodings.gzip = gzippedContent;\n\n      log.info(`compressed ${file.originalPath} [${bytesToSize(originalSize)} -> ${bytesToSize(gzippedContent.length)}]`);\n      done(null, content);\n    });\n  };\n}\n\nPreprocessor.$inject = ['config.gzip', 'logger'];\n\nmodule.exports = {\n  'preprocessor:gzip': ['factory', Preprocessor]\n};\n"
  },
  {
    "path": "fixtures/browser/karma.babel.conf.js",
    "content": "const path = require('path');\nconst gzipPreprocessor = require('./gzip/gzippreprocessor');\nconst resolve = (pkg) => path.join(__dirname, '../../packages', pkg, 'dist', 'index.dev.mjs');\nconst useInfernoCompatPkg = process.env.InfernoCompat === '1';\n\nconsole.info('*** Starting karma tests, Inferno-compat is ' + (useInfernoCompatPkg ? 'on.' : 'off.') + ' ***');\n\nconst preProcessorOptions = {};\n\nif (useInfernoCompatPkg) {\n  preProcessorOptions['./fixtures/browser/test.index.js'] = ['webpack', 'gzip'];\n} else {\n  preProcessorOptions['./fixtures/browser/test.no-compat.index.js'] = ['webpack', 'gzip'];\n}\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '../../',\n\n    frameworks: ['detectBrowsers', 'jasmine'],\n\n    detectBrowsers: {\n      usePhantomJS: false,\n      preferHeadless: false,\n\n      postDetection(browserList) {\n        const results = [];\n\n        if (browserList.includes('Chrome')) {\n          results.push('Chrome');\n        }\n\n        if (browserList.includes('Firefox')) {\n          results.push('Firefox');\n        }\n\n        if (browserList.includes('Edge')) {\n          results.push('Edge');\n        }\n\n        return results;\n      }\n    },\n\n    files: [path.join(__dirname, '../../fixtures/browser/', useInfernoCompatPkg ? 'test.index.js' : 'test.no-compat.index.js')],\n\n    preprocessors: preProcessorOptions,\n\n    plugins: ['karma-detect-browsers', 'karma-jasmine', 'karma-firefox-launcher', 'karma-webpack', gzipPreprocessor, 'karma-chrome-launcher'],\n\n    reporters: ['dots'],\n\n    reportSlowerThan: 500,\n\n    browserConsoleLogOptions: {\n      level: 'warn',\n      terminal: false\n    },\n    colors: true,\n    autoWatch: false,\n    concurrency: 1,\n\n    client: {\n      jasmine: {\n        random: false // Adding jasmine.random false disables test random order\n      },\n      captureConsole: false,\n      logLevel: config.LOG_ERROR\n    },\n\n    webpack: {\n      devtool: false,\n      mode: 'none',\n      optimization: {\n        splitChunks: false,\n        runtimeChunk: false,\n        minimize: false\n      },\n      target: ['web'],\n      module: {\n        rules: [\n          {\n            test: /\\.(js|jsx|tsx|ts)$/,\n            loader: path.join(__dirname, 'node_modules/babel-loader'),\n            options: {\n              babelrc: false,\n              presets: [\n                '@babel/typescript',\n                [\n                  '@babel/preset-env',\n                  {\n                    loose: true,\n                    // es2022\n                    \"targets\": [\n                      \"chrome >= 107\",\n                      \"firefox >= 105\",\n                      \"edge >= 107\"\n                    ]\n                  }\n                ]\n              ],\n              plugins: [\n                ['babel-plugin-inferno', { imports: true }],\n                ['@babel/plugin-proposal-class-properties', { loose: true }]\n              ]\n            }\n          }\n        ]\n      },\n      resolve: {\n        alias: {\n          inferno: resolve('inferno'),\n          'inferno-animation': resolve('inferno-animation'),\n          'inferno-compat': resolve('inferno-compat'),\n          'inferno-create-element': resolve('inferno-create-element'),\n          'inferno-hydrate': resolve('inferno-hydrate'),\n          'inferno-extras': resolve('inferno-extras'),\n          'inferno-hyperscript': resolve('inferno-hyperscript'),\n          'inferno-mobx': resolve('inferno-mobx'),\n          'inferno-redux': resolve('inferno-redux'),\n          'inferno-router': resolve('inferno-router'),\n          'inferno-server': resolve('inferno-server'),\n          'inferno-shared': resolve('inferno-shared'),\n          'inferno-test-utils': resolve('inferno-test-utils'),\n          'inferno-utils': path.join(__dirname, '../../packages', 'inferno-utils', 'src', 'index.ts'),\n          'inferno-vnode-flags': resolve('inferno-vnode-flags'),\n          'inferno-clone-vnode': resolve('inferno-clone-vnode'),\n          mobx: path.join(__dirname, '../../node_modules/mobx/dist/mobx.esm.js')\n        },\n        extensions: ['.js', '.jsx', '.tsx', '.ts'],\n        mainFields: ['browser', 'main']\n      },\n      devServer: {\n        noInfo: true\n      },\n      stats: 'normal',\n      performance: {\n        hints: false\n      }\n    }\n  });\n};\n"
  },
  {
    "path": "fixtures/browser/karma.sauce.conf.js",
    "content": "const path = require('path');\nconst gzipPreprocessor = require('./gzip/gzippreprocessor');\nconst resolve = (pkg) => path.join(__dirname, '../../packages', pkg, 'dist', 'index.dev.mjs');\n\nconst customLaunchers = {\n  slChrome: {\n    base: 'SauceLabs',\n    browserName: 'chrome',\n    browserVersion: 'latest',\n    platform: 'Windows 11'\n  },\n  slSafari14: {\n    base: 'SauceLabs',\n    browserName: 'safari',\n    browserVersion: '16',\n    platform: 'macOS 12'\n  },\n  slSafari15: {\n    base: 'SauceLabs',\n    browserName: 'safari',\n    browserVersion: 'latest',\n    platform: 'macOS 13'\n  },\n  slEdge: {\n    base: 'SauceLabs',\n    browserName: 'MicrosoftEdge',\n    browserVersion: 'latest',\n    platform: 'Windows 11'\n  },\n  sl_mac_chrome: {\n    base: 'SauceLabs',\n    browserName: 'chrome',\n    browserVersion: 'latest',\n    platform: 'macOS 12'\n  },\n  slFirefox: {\n    base: 'SauceLabs',\n    browserName: 'firefox',\n    browserVersion: 'latest'\n  },\n  slFirefox119: {\n    base: 'SauceLabs',\n    browserName: 'firefox',\n    browserVersion: '119',\n    platform: 'Linux',\n    'sauce:options': {\n      geckodriverVersion: '0.33.0'\n    }\n  }\n};\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '../../',\n\n    frameworks: ['jasmine'],\n\n    files: [path.join(__dirname, '../../fixtures/browser/test.index.js')],\n\n    preprocessors: {\n      './fixtures/browser/test.index.js': ['webpack', 'gzip']\n    },\n\n    client: {\n      jasmine: {\n        random: false // Adding jasmine.random false disables test random order\n      }\n    },\n\n    reporters: ['dots', 'saucelabs'],\n    sauceLabs: {\n      startConnect: true,\n      testName: `InfernoJS`,\n      recordVideo: false,\n      recordScreenshots: false,\n      videoUploadOnPass: false,\n      recordLogs: false,\n      captureHtml: false,\n      commandTimeout: 400\n    },\n\n    plugins: ['karma-jasmine', 'karma-webpack', gzipPreprocessor, 'havunen-karma-sauce-launcher2'],\n\n    customLaunchers: customLaunchers,\n    browsers: Object.keys(customLaunchers),\n\n    reportSlowerThan: 2000,\n\n    captureTimeout: 600000,\n    browserNoActivityTimeout: 600000,\n    browserDisconnectTolerance: 2,\n    processKillTimeout: 20000,\n    browserDisconnectTimeout: 10000,\n\n    browserConsoleLogOptions: {\n      level: 'warn',\n      terminal: false\n    },\n    colors: true,\n    singleRun: true,\n    autoWatch: false,\n    concurrency: 1,\n\n    webpack: {\n      devtool: false,\n      mode: 'none',\n      optimization: {\n        splitChunks: false,\n        runtimeChunk: false,\n        minimize: true\n      },\n      target: ['web'],\n      module: {\n        rules: [\n          {\n            test: /\\.(ts|tsx|js|jsx)$/,\n            exclude: /(node_modules)/,\n            use: {\n              loader: 'swc-loader',\n              options: {\n                \"jsc\": {\n                  \"parser\": {\n                    \"syntax\": \"typescript\",\n                    \"tsx\": true,\n                  },\n                  \"experimental\": {\n                    \"plugins\": [\n                      [\"swc-plugin-inferno\", {}]\n                    ],\n                  },\n                  \"target\": \"es2022\",\n                  \"loose\": true\n                }\n              }\n            },\n          }\n        ]\n      },\n      resolve: {\n        alias: {\n          inferno: resolve('inferno'),\n          'inferno-animation': resolve('inferno-animation'),\n          'inferno-compat': resolve('inferno-compat'),\n          'inferno-create-element': resolve('inferno-create-element'),\n          'inferno-hydrate': resolve('inferno-hydrate'),\n          'inferno-extras': resolve('inferno-extras'),\n          'inferno-hyperscript': resolve('inferno-hyperscript'),\n          'inferno-mobx': resolve('inferno-mobx'),\n          'inferno-redux': resolve('inferno-redux'),\n          'inferno-router': resolve('inferno-router'),\n          'inferno-server': resolve('inferno-server'),\n          'inferno-shared': resolve('inferno-shared'),\n          'inferno-test-utils': resolve('inferno-test-utils'),\n          'inferno-utils': path.join(__dirname, '../../packages', 'inferno-utils', 'src', 'index.ts'),\n          'inferno-vnode-flags': resolve('inferno-vnode-flags'),\n          'inferno-clone-vnode': resolve('inferno-clone-vnode'),\n          mobx: path.join(__dirname, '../../node_modules/mobx/dist/mobx.esm.js')\n        },\n        extensions: ['.js', '.jsx', '.tsx', '.ts'],\n        mainFields: ['browser', 'main']\n      },\n      devServer: {\n        noInfo: true\n      },\n      stats: 'errors-only',\n      performance: {\n        hints: false\n      }\n    }\n  });\n};\n"
  },
  {
    "path": "fixtures/browser/karma.swc.conf.js",
    "content": "const path = require('path');\nconst gzipPreprocessor = require('./gzip/gzippreprocessor');\nconst resolve = (pkg) => path.join(__dirname, '../../packages', pkg, 'dist', 'index.dev.mjs');\nconst useInfernoCompatPkg = process.env.InfernoCompat === '1';\n\nconsole.info('*** Starting karma tests, Inferno-compat is ' + (useInfernoCompatPkg ? 'on.' : 'off.') + ' ***');\n\nconst preProcessorOptions = {};\n\nif (useInfernoCompatPkg) {\n  preProcessorOptions['./fixtures/browser/test.index.js'] = ['webpack', 'gzip'];\n} else {\n  preProcessorOptions['./fixtures/browser/test.no-compat.index.js'] = ['webpack', 'gzip'];\n}\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '../../',\n\n    frameworks: ['detectBrowsers', 'jasmine'],\n\n    detectBrowsers: {\n      usePhantomJS: false,\n      preferHeadless: false,\n\n      postDetection(browserList) {\n        const results = [];\n\n        if (browserList.includes('Chrome')) {\n          results.push('Chrome');\n        }\n\n        if (browserList.includes('Firefox')) {\n          results.push('Firefox');\n        }\n\n        if (browserList.includes('Edge')) {\n          results.push('Edge');\n        }\n\n        return results;\n      }\n    },\n\n    files: [path.join(__dirname, '../../fixtures/browser/', useInfernoCompatPkg ? 'test.index.js' : 'test.no-compat.index.js')],\n\n    preprocessors: preProcessorOptions,\n\n    plugins: ['karma-detect-browsers', 'karma-jasmine', 'karma-firefox-launcher', 'karma-webpack', gzipPreprocessor, 'karma-chrome-launcher'],\n\n    reporters: ['dots'],\n\n    reportSlowerThan: 500,\n\n    browserConsoleLogOptions: {\n      level: 'warn',\n      terminal: false\n    },\n    colors: true,\n    autoWatch: false,\n    concurrency: 1,\n\n    client: {\n      jasmine: {\n        random: false // Adding jasmine.random false disables test random order\n      },\n      captureConsole: false,\n      logLevel: config.LOG_ERROR\n    },\n\n    webpack: {\n      devtool: false,\n      mode: 'none',\n      optimization: {\n        splitChunks: false,\n        runtimeChunk: false,\n        minimize: false\n      },\n      target: ['web'],\n      module: {\n        rules: [\n          {\n            test: /\\.(ts|tsx|js|jsx)$/,\n            exclude: /(node_modules)/,\n            use: {\n              loader: 'swc-loader',\n              options: {\n                \"jsc\": {\n                  \"parser\": {\n                    \"syntax\": \"typescript\",\n                    \"tsx\": true,\n                  },\n                  \"experimental\": {\n                    \"plugins\": [\n                      [\"swc-plugin-inferno\", {}]\n                    ],\n                  },\n                  \"target\": \"es2022\",\n                  \"loose\": true\n                }\n              }\n            },\n          }\n        ]\n      },\n      resolve: {\n        alias: {\n          inferno: resolve('inferno'),\n          'inferno-animation': resolve('inferno-animation'),\n          'inferno-compat': resolve('inferno-compat'),\n          'inferno-create-element': resolve('inferno-create-element'),\n          'inferno-hydrate': resolve('inferno-hydrate'),\n          'inferno-extras': resolve('inferno-extras'),\n          'inferno-hyperscript': resolve('inferno-hyperscript'),\n          'inferno-mobx': resolve('inferno-mobx'),\n          'inferno-redux': resolve('inferno-redux'),\n          'inferno-router': resolve('inferno-router'),\n          'inferno-server': resolve('inferno-server'),\n          'inferno-shared': resolve('inferno-shared'),\n          'inferno-test-utils': resolve('inferno-test-utils'),\n          'inferno-utils': path.join(__dirname, '../../packages', 'inferno-utils', 'src', 'index.ts'),\n          'inferno-vnode-flags': resolve('inferno-vnode-flags'),\n          'inferno-clone-vnode': resolve('inferno-clone-vnode'),\n          mobx: path.join(__dirname, '../../node_modules/mobx/dist/mobx.esm.js')\n        },\n        extensions: ['.js', '.jsx', '.tsx', '.ts'],\n        mainFields: ['browser', 'main']\n      },\n      stats: 'normal',\n      performance: {\n        hints: false\n      }\n    }\n  });\n};\n"
  },
  {
    "path": "fixtures/browser/karma.ts.conf.js",
    "content": "const path = require('path');\nconst gzipPreprocessor = require('./gzip/gzippreprocessor');\nconst transformInferno = require('ts-plugin-inferno').default;\nconst resolve = (pkg) => path.join(__dirname, '../../packages', pkg, 'dist', 'index.dev.mjs');\nconst useInfernoCompatPkg = process.env.InfernoCompat === '1';\n\nconsole.info('*** Starting karma tests, Inferno-compat is ' + (useInfernoCompatPkg ? 'on.' : 'off.') + ' ***');\n\nconst preProcessorOptions = {};\n\nif (useInfernoCompatPkg) {\n  preProcessorOptions['./fixtures/browser/test.index.js'] = ['webpack', 'gzip'];\n} else {\n  preProcessorOptions['./fixtures/browser/test.no-compat.index.js'] = ['webpack', 'gzip'];\n}\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '../../',\n\n    frameworks: ['detectBrowsers', 'jasmine'],\n\n    detectBrowsers: {\n      usePhantomJS: false,\n      preferHeadless: false,\n\n      postDetection(browserList) {\n        const results = [];\n\n        if (browserList.includes('Chrome')) {\n          results.push('Chrome');\n        }\n\n        if (browserList.includes('Firefox')) {\n          results.push('Firefox');\n        }\n\n        if (browserList.includes('Edge')) {\n          results.push('Edge');\n        }\n\n        return results;\n      }\n    },\n\n    files: [path.join(__dirname, '../../fixtures/browser/', useInfernoCompatPkg ? 'test.index.js' : 'test.no-compat.index.js')],\n\n    preprocessors: preProcessorOptions,\n\n    plugins: ['karma-detect-browsers', 'karma-jasmine', 'karma-firefox-launcher', 'karma-webpack', gzipPreprocessor, 'karma-chrome-launcher'],\n\n    reporters: ['dots'],\n\n    reportSlowerThan: 500,\n\n    browserConsoleLogOptions: {\n      level: 'warn',\n      terminal: false\n    },\n    colors: true,\n    autoWatch: false,\n    concurrency: 1,\n\n    client: {\n      jasmine: {\n        random: false // Adding jasmine.random false disables test random order\n      },\n      captureConsole: false,\n      logLevel: config.LOG_ERROR\n    },\n\n    webpack: {\n      devtool: false,\n      mode: 'none',\n      optimization: {\n        splitChunks: false,\n        runtimeChunk: false,\n        minimize: false\n      },\n      target: ['web'],\n      module: {\n        rules: [\n          {\n            test: /\\.(ts|tsx)$/,\n            loader: path.join(__dirname, 'node_modules/ts-loader'),\n            options: {\n              compilerOptions: {\n                module: 'es6',\n                target: 'es2022',\n                jsx: 'preserve',\n                allowJs: true,\n                moduleResolution: 'node'\n              },\n              getCustomTransformers: () => ({\n                after: [transformInferno()]\n              })\n            }\n          },\n          {\n            test: /\\.(js|jsx)$/,\n            loader: path.join(__dirname, 'node_modules/babel-loader'),\n            options: {\n              babelrc: false,\n              presets: [\n                [\n                  '@babel/preset-env',\n                  {\n                    loose: true,\n                    // es2022\n                    \"targets\": [\n                      \"chrome >= 107\",\n                      \"firefox >= 105\",\n                      \"edge >= 107\"\n                    ]\n                  }\n                ],\n                '@babel/typescript'\n              ],\n              plugins: [\n                ['babel-plugin-inferno', { imports: true }],\n                ['@babel/plugin-proposal-class-properties', { loose: true }]\n              ]\n            }\n          }\n        ]\n      },\n      resolve: {\n        alias: {\n          inferno: resolve('inferno'),\n          'inferno-animation': resolve('inferno-animation'),\n          'inferno-compat': resolve('inferno-compat'),\n          'inferno-create-element': resolve('inferno-create-element'),\n          'inferno-hydrate': resolve('inferno-hydrate'),\n          'inferno-extras': resolve('inferno-extras'),\n          'inferno-hyperscript': resolve('inferno-hyperscript'),\n          'inferno-mobx': resolve('inferno-mobx'),\n          'inferno-redux': resolve('inferno-redux'),\n          'inferno-router': resolve('inferno-router'),\n          'inferno-server': resolve('inferno-server'),\n          'inferno-shared': resolve('inferno-shared'),\n          'inferno-test-utils': resolve('inferno-test-utils'),\n          'inferno-utils': path.join(__dirname, '../../packages', 'inferno-utils', 'src', 'index.ts'),\n          'inferno-vnode-flags': resolve('inferno-vnode-flags'),\n          'inferno-clone-vnode': resolve('inferno-clone-vnode'),\n          mobx: path.join(__dirname, '../../node_modules/mobx/dist/mobx.esm.js')\n        },\n        extensions: ['.js', '.jsx', '.tsx', '.ts'],\n        mainFields: ['browser', 'main']\n      },\n      devServer: {\n        noInfo: true\n      },\n      stats: 'normal',\n      performance: {\n        hints: false\n      }\n    }\n  });\n};\n"
  },
  {
    "path": "fixtures/browser/package.json",
    "content": "{\n  \"name\": \"inferno-fixture-browser\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"karma start ./karma.sauce.conf.js --single-run\",\n    \"test:babel\": \"karma start ./karma.babel.conf.js --single-run --reporters dots\",\n    \"test:ts\": \"karma start ./karma.ts.conf.js --single-run --reporters dots\",\n    \"test:swc\": \"karma start ./karma.swc.conf.js --single-run --reporters dots\",\n    \"tsDebug\": \"node --inspect-brk node_modules/karma/bin/karma start ./karma.ts.conf.js --no-single-run\",\n    \"debug:sauce\": \"node --inspect-brk node_modules/karma/bin/karma start ./karma.sauce.conf.js --no-single-run\",\n    \"debug:babel\": \"karma start ./karma.babel.conf.js --no-single-run\",\n    \"debug:ts\": \"karma start ./karma.ts.conf.js --no-single-run\",\n    \"debug:swc\": \"karma start ./karma.swc.conf.js --no-single-run\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@babel/core\": \"7.29.0\",\n    \"@babel/preset-env\": \"7.29.0\",\n    \"babel-loader\": \"^10.0.0\",\n    \"build-time-reporter-webpack-plugin\": \"^1.4.3\",\n    \"jasmine-core\": \"^6.0.1\",\n    \"karma\": \"^6.4.4\",\n    \"karma-chrome-launcher\": \"^3.2.0\",\n    \"karma-detect-browsers\": \"^2.3.3\",\n    \"karma-firefox-launcher\": \"^2.1.3\",\n    \"karma-jasmine\": \"^5.1.0\",\n    \"havunen-karma-sauce-launcher2\": \"^6.0.3\",\n    \"karma-webpack\": \"5.0.1\",\n    \"output-compile-time-webpack-plugin\": \"^1.0.5\",\n    \"saucelabs\": \"9.0.2\",\n    \"ts-loader\": \"^9.5.4\",\n    \"webpack\": \"^5.105.2\"\n  }\n}\n"
  },
  {
    "path": "fixtures/browser/test.index.js",
    "content": "// This file includes all test files including inferno-compat\nfunction requireAll(r) {\n  r.keys().forEach(r);\n}\n\nwindow.process = window.process || {};\nwindow.process.env = window.process.env || {};\nwindow.process.env.NODE_ENV = 'development';\n\nrequireAll(require.context('../../packages/inferno/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-clone-vnode/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-compat/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-create-element/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-extras/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-hydrate/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-hyperscript/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-mobx/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-redux/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-router/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-test-utils/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-utils/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\n"
  },
  {
    "path": "fixtures/browser/test.no-compat.index.js",
    "content": "// This file includes all test files except inferno-compat\nfunction requireAll(r) {\n  r.keys().forEach(r);\n}\n\nwindow.process = window.process || {};\nwindow.process.env = window.process.env || {};\nwindow.process.env.NODE_ENV = 'development';\n\nrequireAll(require.context('../../packages/inferno/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-clone-vnode/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-create-element/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-extras/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-hydrate/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-hyperscript/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-mobx/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-redux/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-router/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-test-utils/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\nrequireAll(require.context('../../packages/inferno-utils/__tests__', true, /\\.(js|jsx|tsx|ts)$/));\n"
  },
  {
    "path": "jest.config-nodom.js",
    "content": "import defaultSettings from \"./jest.config.js\";\n\nexport default {\n  ...defaultSettings,\n  setupFiles: [],\n  testMatch: [\n    \"<rootDir>/packages/*/__tests__/**/*spec.server-nodom.@(js|ts)?(x)\"\n  ],\n  testPathIgnorePatterns: [\n    \"<rootDir>/packages/inferno/__tests__/transition.spec.tsx\",\n  ],\n  testEnvironment: \"node\",\n}\n"
  },
  {
    "path": "jest.config.js",
    "content": "export default {\n  collectCoverageFrom: [\n    \"packages/*/src/**/*.ts\",\n    \"!**/*.ts.js\",\n    \"!**/inferno-utils/**/*\",\n    \"!**/inferno-router/**/utils.ts\",\n  ],\n  coverageDirectory: \"coverage\",\n  coverageReporters: [\"html\", \"lcov\", \"text\"],\n  globals: {\n    usingJSDOM: true,\n    usingJest: true\n  },\n  moduleFileExtensions: [\"ts\", \"tsx\", \"js\", \"jsx\"],\n  moduleNameMapper: {\n    \"^inferno-router/utils\": \"<rootDir>/packages/inferno-router/src/utils.ts\",\n    \"^inferno(.*?)$\": \"<rootDir>/packages/inferno$1/src/index.ts\",\n    \"mobx\": \"<rootDir>/node_modules/mobx/dist/mobx.cjs.development.js\"\n  },\n  setupFiles: [\"<rootDir>/scripts/test/requestAnimationFrame.ts\"],\n  testMatch: [\n    \"<rootDir>/packages/*/__tests__/**/*spec.@(js|ts)?(x)\",\n    \"<rootDir>/packages/*/__tests__/**/*spec.server.@(js|ts)?(x)\"\n  ],\n  testPathIgnorePatterns: [\n    \"<rootDir>/packages/inferno/__tests__/transition.spec.tsx\",\n  ],\n  transform: {\n    \"^.+\\\\.(t|j)sx?$\": ['@swc/jest', {\n      \"jsc\": {\n        \"parser\": {\n          \"syntax\": \"typescript\",\n          \"tsx\": true,\n        },\n        \"experimental\": {\n          \"plugins\": [\n            [\"swc-plugin-inferno\", {\n              \"pure\": false\n            }]\n          ],\n        },\n        \"target\": \"es2022\",\n        \"loose\": true\n      }\n    }],\n  },\n  testEnvironment: \"jsdom\",\n  testRunner: \"jest-jasmine2\",\n  reporters: [[\"jest-silent-reporter\", { \"useDots\": true }]]\n}\n"
  },
  {
    "path": "lerna.json",
    "content": "{\n  \"command\": {\n    \"init\": {\n      \"exact\": true\n    },\n    \"bootstrap\": {\n      \"npmClientArgs\": [\"--no-package-lock\"]\n    }\n  },\n  \"packages\": [\"packages/*\"],\n  \"ignoreChanges\": [\"docs/**\", \"packages/*/package-lock.json\"],\n  \"version\": \"9.0.11\"\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"inferno-build\",\n  \"private\": true,\n  \"license\": \"MIT\",\n  \"author\": {\n    \"name\": \"Dominic Gannaway\",\n    \"email\": \"dg@domgan.com\"\n  },\n  \"type\": \"module\",\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+ssh://git@github.com/infernojs/inferno.git\"\n  },\n  \"workspaces\": [\n    \"packages/inferno\",\n    \"packages/inferno-compat\",\n    \"packages/inferno-animation\",\n    \"packages/inferno-create-element\",\n    \"packages/inferno-hydrate\",\n    \"packages/inferno-extras\",\n    \"packages/inferno-hyperscript\",\n    \"packages/inferno-mobx\",\n    \"packages/inferno-redux\",\n    \"packages/inferno-router\",\n    \"packages/inferno-server\",\n    \"packages/inferno-shared\",\n    \"packages/inferno-clone-vnode\",\n    \"packages/inferno-test-utils\",\n    \"packages/inferno-utils\",\n    \"packages/inferno-vnode-flags\"\n  ],\n  \"scripts\": {\n    \"clean\": \"lerna exec -- rimraf dist tmpDist .rpt2_cache_development .rpt2_cache_production package-lock.json\",\n    \"coveralls\": \"coveralls < coverage/lcov.info\",\n    \"debug\": \"node --inspect-brk ./node_modules/jest/bin/jest --runInBand --no-cache --no-watchman\",\n    \"docs-build\": \"cross-env NODE_ENV=production node docs/build.js\",\n    \"docs-build:dev\": \"node docs/build.js\",\n    \"prebuild\": \"npm run clean\",\n    \"postbuild\": \"rimraf build; lerna exec -- rimraf tmpDist\",\n    \"build\": \"npm run clean && tsc --build && npm run build:move-compiled && npm run build:move-types && npm run build:bundle && npm run print:size\",\n    \"build:bundle\": \"lerna exec --stream -- node ../../scripts/rollup/build.js\",\n    \"build:move-types\": \"lerna exec -- node ../../scripts/bundle/move-typedefs.js\",\n    \"build:move-compiled\": \"lerna exec -- node ../../scripts/bundle/move-compiled.js\",\n    \"print:size\": \"node scripts/bundle/bundle-size.js\",\n    \"install:browsertest\": \"cd fixtures/browser && npm install\",\n    \"lint\": \"eslint packages/*\",\n    \"lint:fix\": \"eslint --fix packages/*\",\n    \"publish\": \"lerna publish --exact --force-publish=*\",\n    \"alpha\": \"lerna publish prerelease --dist-tag next --exact --force-publish=*\",\n    \"version\": \"npm run build && npm run docs-build && git add docs && npm run test\",\n    \"postinstall\": \"npm run install:browsertest && npm run build\",\n    \"prettier\": \"prettier --write packages/*\",\n    \"test\": \"npm run test:node && npm run test:node-nodom && npm run test:browser\",\n    \"test:transformers\": \"cross-env InfernoCompat=0 npm run --prefix fixtures/browser test:swc && npm run --prefix fixtures/browser test:ts && npm run --prefix fixtures/browser test:swc\",\n    \"test:node\": \"cross-env NODE_ENV=test jest --config ./jest.config.js --no-watchman\",\n    \"test:node:debug\": \"cross-env NODE_ENV=test node --inspect-brk node_modules/jest/bin/jest.js --config ./jest.config-nodom.js --no-watchman --runInBand\",\n    \"test:node-nodom\": \"cross-env NODE_ENV=test jest --config ./jest.config-nodom.js --no-watchman\",\n    \"test:coverage\": \"cross-env NODE_ENV=test jest --runInBand --coverage --no-watchman\",\n    \"test:browser\": \"npm run test:browser:nocompat && npm run test:browser:compat\",\n    \"test:browser:compat\": \"cross-env InfernoCompat=1 npm run --prefix fixtures/browser test:swc\",\n    \"test:browser:nocompat\": \"cross-env InfernoCompat=0 npm run --prefix fixtures/browser test:swc\",\n    \"test:browser:debug\": \"cross-env InfernoCompat=1 npm run --prefix fixtures/browser debug:swc\",\n    \"test:browser:debug-nocompat\": \"cross-env InfernoCompat=0 npm run --prefix fixtures/browser debug:swc\",\n    \"test:browser:sauce\": \"npm run --prefix fixtures/browser test\",\n    \"test:react\": \"npm run --prefix fixtures/react test -- --forceExit\",\n    \"test:memory\": \"node --expose-gc scripts/fakedom/uibench-reactlike/start.js\",\n    \"test:memory:js-framework\": \"node --expose-gc scripts/fakedom/js-framework-bench/start.js\",\n    \"test:memory:lifecycle\": \"node --expose-gc scripts/fakedom/uibench-lifecycle/start.js\",\n    \"test:memory:lifecycle:debug\": \"node --inspect-brk --expose-gc scripts/fakedom/uibench-lifecycle/start.js\",\n    \"test:memory:js-framework:debug\": \"node --inspect-brk --expose-gc scripts/fakedom/js-framework-bench/start.js\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.29.0\",\n    \"@babel/plugin-proposal-class-properties\": \"7.18.6\",\n    \"@babel/plugin-transform-modules-commonjs\": \"^7.28.6\",\n    \"@babel/preset-env\": \"7.29.0\",\n    \"@babel/preset-typescript\": \"^7.28.5\",\n    \"@eslint/js\": \"^10.0.1\",\n    \"@rollup/plugin-alias\": \"^6.0.0\",\n    \"@rollup/plugin-babel\": \"^6.1.0\",\n    \"@rollup/plugin-commonjs\": \"^29.0.0\",\n    \"@rollup/plugin-json\": \"^6.1.0\",\n    \"@rollup/plugin-node-resolve\": \"^16.0.3\",\n    \"@rollup/plugin-replace\": \"^6.0.3\",\n    \"@rollup/plugin-terser\": \"^0.4.4\",\n    \"@swc/core\": \"1.15.11\",\n    \"@swc/jest\": \"^0.2.39\",\n    \"@types/jest\": \"^30.0.0\",\n    \"@types/jsdom\": \"^27.0.0\",\n    \"@types/node\": \"^25.2.3\",\n    \"@typescript-eslint/eslint-plugin\": \"^8.55.0\",\n    \"@typescript-eslint/parser\": \"^8.55.0\",\n    \"babel-plugin-inferno\": \"6.8.5\",\n    \"cli-table\": \"^0.3.11\",\n    \"concat-stream\": \"^2.0.0\",\n    \"coveralls-next\": \"^6.0.1\",\n    \"cross-env\": \"^10.1.0\",\n    \"d3-scale-chromatic\": \"^3.1.0\",\n    \"eslint\": \"^10\",\n    \"eslint-config-prettier\": \"^10.1.8\",\n    \"eslint-plugin-import\": \"^2.32.0\",\n    \"eslint-plugin-inferno\": \"^7.40.0\",\n    \"eslint-plugin-prettier\": \"^5.5.5\",\n    \"eslint-plugin-promise\": \"^7.2.1\",\n    \"filesize\": \"^11.0.13\",\n    \"globals\": \"^17.3.0\",\n    \"gzip-size\": \"^7.0.0\",\n    \"history\": \"^5.3.0\",\n    \"jest\": \"^30.2.0\",\n    \"jest-environment-jsdom\": \"^30.2.0\",\n    \"jest-jasmine2\": \"^30.2.0\",\n    \"jest-silent-reporter\": \"^0.6.0\",\n    \"jsdom\": \"^28.0.0\",\n    \"lerna\": \"^9\",\n    \"minimist\": \"^1.2.8\",\n    \"mobx\": \"^6.15.0\",\n    \"perf-monitor\": \"^0.6.0\",\n    \"prettier\": \"^3.8.1\",\n    \"rimraf\": \"^6\",\n    \"rollup\": \"4.57.1\",\n    \"swc-loader\": \"^0.2.7\",\n    \"swc-plugin-inferno\": \"^2.13.0\",\n    \"ts-plugin-inferno\": \"^6.1.1\",\n    \"typescript\": \"^5.9.3\",\n    \"typescript-eslint\": \"^8.55.0\"\n  }\n}\n"
  },
  {
    "path": "packages/inferno/README.md",
    "content": "<p align=\"center\"><a href=\"https://infernojs.org/\" target=\"_blank\"><img width=\"150\" alt=\"Inferno\" title=\"Inferno\" src=\"https://user-images.githubusercontent.com/2021355/36063342-626d7ea8-0e84-11e8-84e1-f22bb3b8c4d5.png\"/></a></p>\n\n[![Build Status](https://github.com/infernojs/inferno/workflows/CI/badge.svg)](https://github.com/infernojs/inferno/actions)\n[![Coverage Status](https://img.shields.io/coveralls/infernojs/inferno/master.svg?style=flat-square)](https://coveralls.io/github/infernojs/inferno?branch=master)\n[![MIT](https://img.shields.io/npm/l/inferno.svg?style=flat-square)](https://github.com/infernojs/inferno/blob/master/LICENSE.md)\n[![NPM](https://img.shields.io/npm/v/inferno.svg?style=flat-square)](https://www.npmjs.com/package/inferno)\n[![npm downloads](https://img.shields.io/npm/dm/inferno.svg?style=flat-square)](https://www.npmjs.org/package/inferno)\n[![Discord](https://img.shields.io/discord/825669396823015496.svg?style=flat-square&label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/SUKuhgaBpF)\n[![gzip size](http://img.badgesize.io/https://unpkg.com/inferno/dist/inferno.min.js?compression=gzip)](https://unpkg.com/inferno/dist/inferno.min.js)\n[![Backers on Open Collective](https://opencollective.com/inferno/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/inferno/sponsors/badge.svg)](#sponsors)\n\nInferno is an insanely fast, React-like library for building high-performance user interfaces on both the client and server.\n\n## Description\n\nThe main objective of the InfernoJS project is to provide the fastest possible **runtime** performance for web applications. Inferno excels at rendering real time data views or large DOM trees.\n\nThe performance is achieved through multiple optimizations, for example:\n\n- Inferno's own JSX compilers creates monomorphic `createVNode` calls, instead of `createElement` calls.\n  Optimizing runtime performance of the application.\n  - [SWC plugin inferno](https://github.com/infernojs/swc-plugin-inferno) is a plugin for [SWC](https://swc.rs/). It can compile TSX and JSX\n  - [Babel plugin inferno](https://github.com/infernojs/babel-plugin-inferno) is a plugin for [BabelJs](https://babeljs.io/). It can compile JSX.\n  - [TS plugin inferno](https://github.com/infernojs/ts-plugin-inferno) is a plugin for [TSC](https://www.typescriptlang.org/). It can compile TSX.\n- Inferno's diff process uses bitwise flags to memoize the shape of objects\n- Child nodes are normalized only when needed\n- Special JSX flags can be used during compile time to optimize runtime performance at application level\n- Many micro optimizations\n\n## Features\n\n- Component driven + one-way data flow architecture\n- React-like API, concepts and component lifecycle events\n- Partial synthetic event system, normalizing events for better cross browser support\n- Inferno's [`linkEvent`](https://github.com/infernojs/inferno/blob/master/README.md#linkevent-package-inferno) feature removes the need to use arrow functions or binding event callbacks\n- Isomorphic rendering on both client and server with `inferno-server`\n- Unlike React and Preact, Inferno has lifecycle events on functional components\n- Unlike Preact and other React-like libraries, Inferno has controlled components for input/select/textarea elements\n- Components can be rendered outside their current html hierarchy using `createPortal` - API\n- Support for [older browsers](https://github.com/infernojs/inferno#browser-support) without any polyfills\n- defaultHooks for Functional components, this way re-defining lifecycle events per usage can be avoided\n- Inferno supports setting styles using string `<div style=\"background-color: red\"></div>` or using object literal syntax `<div style={{\"background-color\": \"red\"}}></div>`. For camelCase syntax support see [`inferno-compat`](https://github.com/infernojs/inferno/tree/master/packages/inferno-compat).\n- Fragments (v6)\n- createRef and forwardRef APIs (v6)\n- componentDidAppear, componentWillDisappear and componentWillMove (v8) - class and function component callbacks to ease animation work, see [inferno-animation](https://github.com/infernojs/inferno/tree/master/packages/inferno-animation) package\n\n## Runtime requirements\n\nInferno v9 requires following features to be present in the executing runtime:\n\n- `Promise`\n- `String.prototype.includes()`\n- `String.prototype.startsWith()`\n- `Array.prototype.includes()`\n- `Object.spread()`\n\n## Browser support\n\nSince version 4 we have started running our test suite **without** any polyfills.\nInferno is now part of [Saucelabs](https://saucelabs.com/) open source program and we use their service for executing the tests.\n\nInfernoJS is actively tested with browsers listed below, however it may run well on older browsers as well.\nThis is due to limited support of browser versions in recent testing frameworks. https://github.com/jasmine/jasmine/blob/main/release_notes/5.0.0.md\n\n[![Browser Test Status](https://app.saucelabs.com/browser-matrix/Havunen.svg)](https://app.saucelabs.com/open_sauce/user/Havunen/tests/vdc)\n\n## Migration guides\n\n- [Inferno v4](https://github.com/infernojs/inferno/blob/master/documentation/v4-migration.md)\n- [Inferno v6](https://github.com/infernojs/inferno/blob/master/documentation/v6-migration.md)\n\n## Benchmarks\n\nLive examples at [https://infernojs.github.io/inferno](https://infernojs.github.io/inferno)\n\n- [UI Bench](https://localvoid.github.io/uibench/)\n- [dbmonster](https://infernojs.github.io/inferno/dbmonster/)\n- [JS Web Frameworks Benchmark (current)](https://krausest.github.io/js-framework-benchmark/current.html)\n- [Isomorphic-UI-Benchmark](https://github.com/marko-js/isomorphic-ui-benchmarks)\n- [1k Components](https://infernojs.github.io/inferno/1kcomponents/)\n\n## Code Example\n\nLet's start with some code. As you can see, Inferno intentionally keeps the same design ideas as React regarding components: one-way data flow and separation of concerns.\n\nIn these examples, JSX is used via the [Inferno JSX Babel Plugin](https://github.com/infernojs/babel-plugin-inferno) to provide a simple way to express Inferno virtual DOM. You do not need to use JSX, it's completely **optional**, you can use [hyperscript](https://github.com/infernojs/inferno/tree/master/packages/inferno-hyperscript) or [createElement](https://github.com/infernojs/inferno/tree/master/packages/inferno-create-element) (like React does).\nKeep in mind that compile time optimizations are available only for JSX.\n\n```jsx\nimport { render } from 'inferno';\n\nconst message = 'Hello world';\n\nrender(<MyComponent message={message} />, document.getElementById('app'));\n```\n\nFurthermore, Inferno also uses ES6 components like React:\n\n```jsx\nimport { render, Component } from 'inferno';\n\nclass MyComponent extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      counter: 0,\n    };\n  }\n  render() {\n    return (\n      <div>\n        <h1>Header!</h1>\n        <span>Counter is at: {this.state.counter}</span>\n      </div>\n    );\n  }\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\nBecause performance is an important aspect of this library, we want to show you how to optimize your application even further.\nIn the example below we optimize diffing process by using JSX **$HasVNodeChildren** and **$HasTextChildren** to predefine children shape compile time.\nIn the MyComponent render method there is a div that contains JSX expression `node` as its content. Due to dynamic nature of Javascript\nthat variable `node` could be anything and Inferno needs to go through the normalization process to make sure there are no nested arrays or other invalid data.\nInferno offers a feature called ChildFlags for application developers to pre-define the shape of vNode's child node. In this example case\nit is using `$HasVNodeChildren` to tell the JSX compiler, that this vNode contains only single element or component vNode.\nNow inferno will not go into the normalization process runtime, but trusts the developer decision about the shape of the object and correctness of data.\nIf this contract is not kept and `node` variable contains invalid value for the pre-defined shape (fe. `null`), then application would crash runtime.\nThere is also span-element in the same render method, which content is set dynamically through `_getText()` method. There `$HasTextChildren` child-flag\nfits nicely, because the content of that given \"span\" is never anything else than text.\nAll the available child flags are documented [here](https://infernojs.org/docs/guides/optimizations).\n\n```jsx\nimport { createTextVNode, render, Component } from 'inferno';\n\nclass MyComponent extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      counter: 0,\n    };\n  }\n\n  _getText() {\n    return 'Hello!';\n  }\n\n  render() {\n    const node =\n      this.state.counter > 0 ? (\n        <div>0</div>\n      ) : (\n        <span $HasTextChildren>{this._getText()}</span>\n      );\n\n    return (\n      <div>\n        <h1>Header!</h1>\n        <div $HasVNodeChildren>{node}</div>\n      </div>\n    );\n  }\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\n### Tear down\n\nTo tear down inferno application you need to render null on root element.\nRendering `null` will trigger unmount lifecycle hooks for whole vDOM tree and remove global event listeners.\nIt is important to unmount unused vNode trees to free browser memory.\n\n```jsx\nimport { createTextVNode, render, Component } from 'inferno';\n\nconst rootElement = document.getElementById('app');\n\n// Start the application\nrender(<ExampleComponent />, rootElement);\n\n// Tear down\nrender(null, rootElement);\n```\n\n### More Examples\n\nIf you have built something using Inferno you can add them here:\n\n- [**Simple Clock** (@JSFiddle)](https://jsfiddle.net/4bha7kcg/)\n- [**Simple JS Counter** (@github/scorsi)](https://github.com/scorsi/simple-counter-inferno-cerebral-fusebox): SSR Inferno (view) + Cerebral (state manager) + FuseBox (build system/bundler)\n- [**Online interface to TMDb movie database** (@codesandbox.io)](https://codesandbox.io/s/9zjo5yx8po): Inferno + [Inferno hyperscript](https://github.com/infernojs/inferno) (view) + [Superagent](https://github.com/visionmedia/superagent) (network requests) + Web component ([custom elements v1](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements)) + [state-transducer](https://github.com/brucou/state-transducer)\n  (state machine library)\n- [**Lemmy - a self-hostable reddit alternative** (front end in Inferno)](https://github.com/dessalines/lemmy)\n\n## Getting Started\n\nThe easiest way to get started with Inferno is by using [Create Inferno App](https://github.com/infernojs/create-inferno-app).\n\nAlternatively, you can try any of the following:\n\n- the [Inferno Boilerplate](https://github.com/infernojs/inferno-boilerplate) for a very simple setup.\n- for a more advanced example demonstrating how Inferno might be used, we recommend trying out [Inferno Starter Project](https://github.com/nightwolfz/inferno-starter) by [nightwolfz](https://github.com/nightwolfz/).\n- for using Inferno to build a mobile app, try [Inferno Mobile Starter Project](https://github.com/Rudy-Zidan/inferno-mobile) by [Rudy-Zidan](https://github.com/Rudy-Zidan).\n- for [TypeScript](https://www.typescriptlang.org/) support and bundling, check out [ts-plugin-inferno](https://github.com/infernojs/ts-plugin-inferno), or [inferno-typescript-example](https://github.com/infernojs/inferno-typescript-example).\n- for an example of how to use Inferno in [codesandbox](https://codesandbox.io/): https://codesandbox.io/s/znmyj24w4p\n- for using [parcel and typescript](https://github.com/jayy-lmao/inferno-parcel-ts)\n\nCore package:\n\n```sh\nnpm install --save inferno\n```\n\nAddons:\n\n```sh\n# server-side rendering\nnpm install --save inferno-server\n# routing\nnpm install --save inferno-router\n```\n\nPre-bundled files for browser consumption can be found on [our cdnjs](https://cdnjs.com/libraries/inferno):\n\nOr on jsDelivr:\n\n```\nhttps://cdn.jsdelivr.net/npm/inferno@latest/dist/inferno.min.js\n```\n\nOr on unpkg.com:\n\n```\nhttps://unpkg.com/inferno@latest/dist/inferno.min.js\n```\n\n### Creating Virtual DOM\n\n#### JSX:\n\n```sh\nnpm install --save-dev babel-plugin-inferno\n```\n\n#### Hyperscript:\n\n```sh\nnpm install --save inferno-hyperscript\n```\n\n#### createElement:\n\n```sh\nnpm install --save inferno-create-element\n```\n\n### Compatibility with existing React apps\n\n```sh\nnpm install --save-dev inferno-compat\n```\n\nNote: Make sure you read more about [`inferno-compat`](https://github.com/infernojs/inferno/tree/master/packages/inferno-compat) before using it.\n\n## Third-party state libraries\n\nInferno now has bindings available for some of the major state management libraries out there:\n\n- Redux via [`inferno-redux`](https://github.com/infernojs/inferno/tree/dev/packages/inferno-redux)\n- MobX via [`inferno-mobx`](https://github.com/infernojs/inferno/tree/dev/packages/inferno-mobx)\n- Cerebral via [`@cerebral/inferno`](https://github.com/cerebral/cerebral/tree/master/packages/node_modules/@cerebral/inferno)\n\n## JSX\n\nInferno has its own [JSX Babel plugin](https://github.com/trueadm/babel-plugin-inferno).\n\n## Differences from React\n\n- Inferno doesn't have a fully synthetic event system like React does. Inferno has a partially synthetic event system, instead opting to only delegate certain events (such as `onClick`).\n- Inferno doesn't support React Native. Inferno was only designed for the browser/server with the DOM in mind.\n- Inferno doesn't support legacy string refs, use `createRef` or callback `ref` API\n- Inferno provides lifecycle events on functional components. This is a major win for people who prefer lightweight components rather than ES2015 classes.\n\n## Differences from Preact\n\n- Inferno has a partial synthetic event system, resulting in better performance via delegation of certain events.\n- Inferno is _much_ faster than Preact in rendering, updating and removing elements from the DOM. Inferno diffs against virtual DOM, rather than the real DOM (except when loading from server-side rendered content), which means it can make drastic improvements. Unfortunately, diffing against the real DOM has a 30-40% overhead cost in operations.\n- Inferno fully supports controlled components for `input`/`select`/`textarea` elements. This prevents lots of edgecases where the virtual DOM is not the source of truth (it should always be). Preact pushes the source of truth to the DOM itself.\n- Inferno provides lifecycle events on functional components. This is a major win for people who prefer lightweight components rather than ES2015 classes.\n\n## Event System\n\nLike React, Inferno also uses a light-weight synthetic event system in certain places (although both event systems differ massively). Inferno's event system provides highly efficient delegation and an event helper called [`linkEvent`](https://github.com/infernojs/inferno/blob/master/README.md#linkevent-package-inferno).\n\nOne major difference between Inferno and React is that Inferno does not rename events or change how they work by default. Inferno only specifies that events should be camel cased, rather than lower case. Lower case events will bypass\nInferno's event system in favour of using the native event system supplied by the browser. For example, when detecting changes on an `<input>` element, in React you'd use `onChange`, with Inferno you'd use `onInput` instead (the\nnative DOM event is `oninput`).\n\nAvailable synthetic events are:\n\n- `onClick`\n- `onDblClick`\n- `onFocusIn`\n- `onFocusOut`\n- `onKeyDown`\n- `onKeyPress`\n- `onKeyUp`\n- `onMouseDown`\n- `onMouseMove`\n- `onMouseUp`\n- `onTouchEnd`\n- `onTouchMove`\n- `onTouchStart`\n\n### `linkEvent` (package: `inferno`)\n\n`linkEvent()` is a helper function that allows attachment of `props`/`state`/`context` or other data to events without needing to `bind()` them or use arrow functions/closures. This is extremely useful when dealing with events in functional components. Below is an example:\n\n```jsx\nimport { linkEvent } from 'inferno';\n\nfunction handleClick(props, event) {\n  props.validateValue(event.target.value);\n}\n\nfunction MyComponent(props) {\n  return <div><input type=\"text\" onClick={ linkEvent(props, handleClick) } /><div>;\n}\n```\n\nThis is an example of using it with ES2015 classes:\n\n```jsx\nimport { linkEvent, Component } from 'inferno';\n\nfunction handleClick(instance, event) {\n  instance.setState({ data: event.target.value });\n}\n\nclass MyComponent extends Component {\n  render () {\n    return <div><input type=\"text\" onClick={ linkEvent(this, handleClick) } /><div>;\n  }\n}\n```\n\n`linkEvent()` offers better performance than binding an event in a class constructor and using arrow functions, so use it where possible.\n\n## Controlled Components\n\nIn HTML, form elements such as `<input>`, `<textarea>`, and `<select>` typically maintain their own state and update it based on user input.\nIn Inferno, mutable state is typically kept in the state property of components, and only updated with `setState()`.\n\nWe can combine the two by making the Inferno state be the \"single source of truth\". Then the Inferno component that renders a form also\ncontrols what happens in that form on subsequent user input. An input form element whose value is controlled by\nInferno in this way is called a \"controlled component\".\n\n## Inferno Top-Level API\n\n### `render` (package: `inferno`)\n\n```javascript\nimport { render } from 'inferno';\n\nrender(<div />, document.getElementById('app'));\n```\n\nRender a virtual node into the DOM in the supplied container given the supplied virtual DOM. If the virtual node was previously rendered\ninto the container, this will perform an update on it and only mutate the DOM as necessary, to reflect the latest Inferno virtual node.\n\nWarning: If the container element is not empty before rendering, the content of the container will be overwritten on the initial render.\n\n### `createRenderer` (package: `inferno`)\n\n`createRenderer` creates an alternative render function with a signature matching that of the first argument passed to a reduce/scan function. This allows for easier integration with reactive programming libraries, like [RxJS](https://github.com/ReactiveX/rxjs) and [Most](https://github.com/cujojs/most).\n\n```javascript\nimport { createRenderer } from 'inferno';\nimport { scan, map } from 'most';\n\nconst renderer = createRenderer();\n\n// NOTE: vNodes$ represents a stream of virtual DOM node updates\nscan(renderer, document.getElementById('app'), vNodes$);\n```\n\nSee [inferno-most-fp-demo](https://github.com/joshburgess/inferno-most-fp-demo) for an example of how to build an app architecture around this.\n\n### `createElement` (package: `inferno-create-element`)\n\nCreates an Inferno VNode using a similar API to that found with React's `createElement()`\n\n```javascript\nimport { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\nclass BasicComponent extends Component {\n  render() {\n    return createElement(\n      'div',\n      {\n        className: 'basic',\n      },\n      createElement(\n        'span',\n        {\n          className: this.props.name,\n        },\n        'The title is ',\n        this.props.title,\n      ),\n    );\n  }\n}\n\nrender(\n  createElement(BasicComponent, { title: 'abc' }),\n  document.getElementById('app'),\n);\n```\n\n### `Component` (package: `inferno`)\n\n**Class component:**\n\n```javascript\nimport { Component } from 'inferno';\n\nclass MyComponent extends Component {\n  render() {\n    return <div>My Component</div>;\n  }\n}\n```\n\nThis is the base class for Inferno Components when they're defined using ES6 classes.\n\n**Functional component:**\n\n```javascript\nconst MyComponent = ({ name, age }) => (\n  <span>\n    My name is: {name} and my age is: {age}\n  </span>\n);\n```\n\nAnother way of using defaultHooks.\n\n```javascript\nexport function Static() {\n  return <div>1</div>;\n}\n\nStatic.defaultHooks = {\n  onComponentShouldUpdate() {\n    return false;\n  },\n};\n```\n\nDefault props\n\n```jsx\nexport function MyFunctionalComponent({ value }) {\n  return <div>{value}</div>;\n}\n\nMyFunctionalComponent.defaultProps = {\n  value: 10,\n};\n```\n\nFunctional components are first-class functions where their first argument is the `props` passed through from their parent.\n\n### `createVNode` (package: `inferno`)\n\n```js\nimport { createVNode } from 'inferno';\n\ncreateVNode(\n  flags,\n  type,\n  [className],\n  [...children],\n  [childFlags],\n  [props],\n  [key],\n  [ref],\n);\n```\n\ncreateVNode is used to create html element's virtual node object. Typically `createElement()` (package: `inferno-create-element`), `h()` (package: `inferno-hyperscript`) or JSX are used to create\n`VNode`s for Inferno, but under the hood they all use `createVNode()`. Below is an example of `createVNode` usage:\n\n```javascript\nimport { VNodeFlags, ChildFlags } from 'inferno-vnode-flags';\nimport { createVNode, createTextVNode, render } from 'inferno';\n\nconst vNode = createVNode(\n  VNodeFlags.HtmlElement,\n  'div',\n  'example',\n  createTextVNode('Hello world!'),\n  ChildFlags.HasVNodeChildren,\n);\n\n// <div class=\"example\">Hello world!</div>\n\nrender(vNode, container);\n```\n\n`createVNode` arguments explained:\n\n`flags`: (number) is a value from [`VNodeFlags`](https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags), this is a numerical value that tells Inferno what the VNode describes on the page.\n\n`type`: (string) is tagName for element for example 'div'\n\n`className`: (string) is the class attribute ( it is separated from props because it is the most commonly used property )\n\n`children`: (vNode[]|vNode) is one or array of vNodes to be added as children for this vNode\n\n`childFlags`: (number) is a value from [`ChildFlags`](https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags), this tells inferno shape of the children so normalization process can be skipped.\n\n`props`: (Object) is object containing all other properties. fe: `{onClick: method, 'data-attribute': 'Hello Community!}`\n\n`key`: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.\n\n`ref`: (function) callback which is called when DOM node is added/removed from DOM.\n\n### `createComponentVNode` (package: 'inferno')\n\n```js\nimport { createComponentVNode } from 'inferno';\n\ncreateComponentVNode(flags, type, [props], [key], [ref]);\n```\n\ncreateComponentVNode is used for creating vNode for Class/Functional Component.\n\nExample:\n\n```javascript\nimport { VNodeFlags, ChildFlags } from 'inferno-vnode-flags';\nimport {\n  createVNode,\n  createTextVNode,\n  createComponentVNode,\n  render,\n} from 'inferno';\n\nfunction MyComponent(props, context) {\n  return createVNode(\n    VNodeFlags.HtmlElement,\n    'div',\n    'example',\n    createTextVNode(props.greeting),\n    ChildFlags.HasVNodeChildren,\n  );\n}\n\nconst vNode = createComponentVNode(\n  VNodeFlags.ComponentFunction,\n  MyComponent,\n  {\n    greeting: 'Hello Community!',\n  },\n  null,\n  {\n    onComponentDidMount() {\n      console.log('example of did mount hook!');\n    },\n  },\n);\n\n// <div class=\"example\">Hello Community!</div>\n\nrender(vNode, container);\n```\n\n`createComponentVNode` arguments explained:\n\n`flags`: (number) is a value from [`VNodeFlags`](https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags), this is a numerical value that tells Inferno what the VNode describes on the page.\n\n`type`: (Function/Class) is the class or function prototype for Component\n\n`props`: (Object) properties passed to Component, can be anything\n\n`key`: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.\n\n`ref`: (Function|Object) this property is object for Functional Components defining all its lifecycle methods. For class Components this is function callback for ref.\n\n### `createTextVNode` (package: 'inferno')\n\ncreateTextVNode is used for creating vNode for text nodes.\n\n`createTextVNode` arguments explained:\ntext: (string) is a value for text node to be created.\nkey: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.\n\n```js\nimport { createTextVNode } from 'inferno';\n\ncreateTextVNode(text, key);\n```\n\n### `cloneVNode` (package: `inferno-clone-vnode`)\n\nThis package has same API as React.cloneElement\n\n```javascript\nimport { cloneVNode } from 'inferno-clone-vnode';\n\ncloneVNode(vNode, [props], [...children]);\n```\n\nClone and return a new Inferno `VNode` using a `VNode` as the starting point. The resulting `VNode` will have the original `VNode`'s props with the new props merged in shallowly. New children will replace existing children. key and ref from the original `VNode` will be preserved.\n\n`cloneVNode()` is almost equivalent to:\n\n```jsx\n<VNode.type {...VNode.props} {...props}>\n  {children}\n</VNode.type>\n```\n\nAn example of using `cloneVNode`:\n\n```javascript\nimport { createVNode, render } from 'inferno';\nimport { cloneVNode } from 'inferno-clone-vnode';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nconst vNode = createVNode(\n  VNodeFlags.HtmlElement,\n  'div',\n  'example',\n  'Hello world!',\n);\nconst newVNode = cloneVNode(vNode, { id: 'new' }); // we are adding an id prop to the VNode\n\nrender(newVNode, container);\n```\n\nIf you're using JSX:\n\n```jsx\nimport { render } from 'inferno';\nimport { cloneVNode } from 'inferno-clone-vnode';\n\nconst vNode = <div className=\"example\">Hello world</div>;\nconst newVNode = cloneVNode(vNode, { id: 'new' }); // we are adding an id prop to the VNode\n\nrender(newVNode, container);\n```\n\n### `createPortal` (package: 'inferno')\n\nHTML:\n\n```html\n<div id=\"root\"></div>\n<div id=\"outside\"></div>\n```\n\nJavascript:\n\n```jsx\nconst { render, Component, version, createPortal } from 'inferno';\n\nfunction Outsider(props) {\n\treturn <div>{`Hello ${props.name}!`}</div>;\n}\n\nconst outsideDiv = document.getElementById('outside');\nconst rootDiv = document.getElementById('root');\n\nfunction App() {\n\treturn (\n  \t    <div>\n    \t    Main view\n            ...\n            {createPortal(<Outsider name=\"Inferno\" />, outsideDiv)}\n        </div>\n    );\n}\n\n\n// render an instance of Clock into <body>:\nrender(<App />, rootDiv);\n```\n\nResults into:\n\n```html\n<div id=\"root\">\n  <div>Main view ...</div>\n</div>\n<div id=\"outside\">\n  <div>Hello Inferno!</div>\n</div>\n```\n\nCool, huh? Updates (props/context) will flow into \"Outsider\" component from the App component the same way as any other Component.\nFor inspiration on how to use it click [here](https://hackernoon.com/using-a-react-16-portal-to-do-something-cool-2a2d627b0202)!\n\n### `createRef` (package: `inferno`)\n\ncreateRef API provides shorter syntax than callback ref when timing of element is not needed.\n\n```jsx\nimport { Component, render, createRef } from 'inferno';\n\nclass Foobar extends Component {\n  constructor(props) {\n    super(props);\n\n    // Store reference somewhere\n    this.element = createRef(); // Returns object {current: null}\n  }\n\n  render() {\n    return (\n      <div>\n        <span id=\"span\" ref={this.element}>\n          Ok\n        </span>\n      </div>\n    );\n  }\n}\n\nrender(<Foobar />, container);\n```\n\n### `createFragment` (package: `inferno`)\n\ncreateFragment is the native way to createFragment vNode. `createFragment(children: any, childFlags: ChildFlags, key?: string | number | null)`\n\n`createFragment` arguments explained:\n\n`children`: (Array) Content of fragment vNode, typically array of VNodes\n\n`childFlags`: (number) is a value from [`ChildFlags`](https://github.com/infernojs/inferno/tree/master/packages/inferno-vnode-flags), this tells inferno shape of the children so normalization process can be skipped.\n\n`key`: (string|number) unique key within this vNodes siblings to identify it during keyed algorithm.\n\nAlternative ways to create fragment vNode are:\n\n- Using JSX `<> ... </>`, `<Fragment> .... </Fragment>` or `<Inferno.Fragment> ... </Inferno.Fragment>`\n- Using createElement API `createElement(Inferno.Fragment, {key: 'test'}, ...children)`\n- Using hyperscript API `h(Inferno.Fragment, {key: 'test'}, children)`\n\nIn the below example both fragments are identical except they have different key\n\n```jsx\nimport { Fragment, render, createFragment } from 'inferno';\nimport { ChildFlags } from 'inferno-vnode-flags';\n\nfunction Foobar() {\n  return (\n    <div $HasKeyedChildren>\n      {createFragment(\n        [<div>Ok</div>, <span>1</span>],\n        ChildFlags.HasNonKeyedChildren,\n        'key1',\n      )}\n      <Fragment key=\"key2\">\n        <div>Ok</div>\n        <span>1</span>\n      </Fragment>\n    </div>\n  );\n}\n\nrender(<Foobar />, container);\n```\n\n### `forwardRef` (package: `inferno`)\n\nforwardRef is a new mechanism to \"forward\" ref inside a functional Component.\nIt can be useful if you have simple functional Components and you want to create reference to a specific element inside it.\n\n```jsx\nimport { forwardRef, Component, render } from 'inferno';\n\nconst FancyButton = forwardRef((props, ref) => (\n  <button ref={ref} className=\"FancyButton\">\n    {props.children}\n  </button>\n));\n\nclass Hello extends Component {\n  render() {\n    return (\n      <FancyButton\n        ref={(btn) => {\n          if (btn) {\n            // btn variable is the button rendered from FancyButton\n          }\n        }}\n      >\n        Click me!\n      </FancyButton>\n    );\n  }\n}\n\nrender(<Hello />, container);\n```\n\n### `hydrate` (package: `inferno-hydrate`)\n\n```javascript\nimport { hydrate } from 'inferno-hydrate';\n\nhydrate(<div />, document.getElementById('app'));\n```\n\nSame as `render()`, but is used to hydrate a container whose HTML contents were rendered by `inferno-server`. Inferno will attempt to attach event listeners to the existing markup.\n\n### `findDOMNode` (package: `inferno-extras`)\n\nThis feature has been moved from inferno to inferno-compat in v6. No options are needed anymore.\n\nNote: we recommend using a `ref` callback on a component to find its instance, rather than using `findDOMNode()`. `findDOMNode()` cannot be used on functional components.\n\nIf a component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements.\nIn most cases, you can attach a ref to the DOM node and avoid using `findDOMNode()` at all. When render returns null or false, `findDOMNode()` returns null.\nIf Component has rendered fragment it returns the first element.\n\n### Inferno Flags (package: inferno-vnode-flags)\n\n**VNodeFlags:**\n\n- `VNodeFlags.HtmlElement`\n- `VNodeFlags.ComponentUnknown`\n- `VNodeFlags.ComponentClass`\n- `VNodeFlags.ComponentFunction`\n- `VNodeFlags.Text`\n- `VNodeFlags.SvgElement`\n- `VNodeFlags.InputElement`\n- `VNodeFlags.TextareaElement`\n- `VNodeFlags.SelectElement`\n- `VNodeFlags.Portal`\n- `VNodeFlags.ReCreate` (JSX **$ReCreate**) always re-creates the vNode\n- `VNodeFlags.ContentEditable`\n- `VNodeFlags.Fragment`\n- `VNodeFlags.InUse`\n- `VnodeFlags.ForwardRef`\n- `VNodeFlags.Normalized`\n\n**VNodeFlags Masks:**\n\n- `VNodeFlags.ForwardRefComponent` Functional component wrapped in forward ref\n- `VNodeFlags.FormElement` - Is form element\n- `VNodeFlags.Element` - Is vNode element\n- `VNodeFlags.Component` - Is vNode Component\n- `VNodeFlags.DOMRef` - Bit set when vNode holds DOM reference\n- `VNodeFlags.InUseOrNormalized` - VNode is used somewhere else or came from normalization process\n- `VNodeFlags.ClearInUseNormalized` - Opposite mask of InUse or Normalized\n\n**ChildFlags**\n\n- `ChildFlags.UnknownChildren` needs Normalization\n- `ChildFlags.HasInvalidChildren` is invalid (null, undefined, false, true)\n- `ChildFlags.HasVNodeChildren` (JSX **$HasVNodeChildren**) is single vNode (Element/Component)\n- `ChildFlags.HasNonKeyedChildren` (JSX **$HasNonKeyedChildren**) is Array of vNodes non keyed (no nesting, no holes)\n- `ChildFlags.HasKeyedChildren` (JSX **$HasKeyedChildren**) is Array of vNodes keyed (no nesting, no holes)\n- `ChildFlags.HasTextChildren` (JSX **$HasTextChildren**) vNode contains only text\n\n**ChildFlags Masks**\n\n- `ChildFlags.MultipleChildren` Is Array\n\n### `renderToString` (package: `inferno-server`)\n\n```javascript\nimport { renderToString } from 'inferno-server';\n\nconst string = renderToString(<div />);\n```\n\nRender a virtual node into an HTML string, given the supplied virtual DOM.\n\n## Functional component lifecycle events\n\n| Name                       | Triggered when                                                 | Arguments to callback      |\n| -------------------------- | -------------------------------------------------------------- | -------------------------- |\n| `onComponentWillMount`     | a functional component is about to mount                       |                            |\n| `onComponentDidMount`      | a functional component has mounted successfully                | `domNode`                  |\n| `onComponentShouldUpdate`  | a functional component has been triggered to update            | `lastProps, nextProps`     |\n| `onComponentWillUpdate`    | a functional component is about to perform an update           | `lastProps, nextProps`     |\n| `onComponentDidUpdate`     | a functional component has performed an update                 | `lastProps, nextProps`     |\n| `onComponentWillUnmount`   | a functional component is about to be unmounted                | `domNode`                  |\n| `onComponentDidAppear`     | a functional component has mounted and is ready for animations | `domNode, props`           |\n| `onComponentWillDisappear` | a functional component is unmounted before DOM node is removed | `domNode, props, callback` |\n\nonComponentWillDisappear has special type of argument \"callback\" which needs to be called when component is ready to be removed from the DOM. fe. after animations are finished.\n\n## Class component lifecycle events\n\nAll these Component lifecycle methods ( including `render` and `setState - callback`) are called with Component instance context. You don't need to \"bind\" these methods.\n\n| Name                              | Triggered when                                                                        | Arguments to callback            |\n| --------------------------------- | ------------------------------------------------------------------------------------- | -------------------------------- |\n| `componentDidMount`               | component has been mounted successfully                                               |                                  |\n| `componentWillMount`              | component is about to mount                                                           |                                  |\n| `componentWillReceiveProps`       | before render when component updates                                                  | `nextProps, context`             |\n| `shouldComponentUpdate`           | component has been triggered to update                                                | `nextProps, nextState`           |\n| `componentWillUpdate`             | component is about to perform an update                                               | `nextProps, nextState, context`  |\n| `componentDidUpdate`              | component has performed an update                                                     | `lastProps, lastState, snapshot` |\n| `componentWillUnmount`            | component is about to be unmounted                                                    |                                  |\n| `getChildContext`                 | before render method, return value object is combined to sub tree context             |                                  |\n| `getSnapshotBeforeUpdate`         | before component updates, return value is sent to componentDidUpdate as 3rd parameter | `lastProps, lastState`           |\n| `static getDerivedStateFromProps` | before render method                                                                  | `nextProps, state`               |\n| `componentDidAppear`              | component has mounted and is ready for animations                                     | `domNode`                        |\n| `componentWillDisappear`          | component is unmounted before DOM node is removed                                     | `domNode, callback`              |\n\ncomponentWillDisappear has special type of argument \"callback\" which needs to be called when component is ready to be removed from the DOM. fe. after animations are finished.\n\n### Using functional lifecycle events\n\nFunctional lifecycle events must be explicitly assigned via props onto a functional component like shown below:\n\n```javascript\nimport { render } from 'inferno';\n\nfunction mounted(domNode) {\n  // [domNode] will be available for DOM nodes and components (if the component has mounted to the DOM)\n}\n\nfunction FunctionalComponent({ props }) {\n  return <div>Hello world</div>;\n}\n\nrender(\n  <FunctionalComponent onComponentDidMount={mounted} />,\n  document.getElementById('app'),\n);\n```\n\nPlease note: class components (ES2015 classes) from `inferno` **do not** support the same lifecycle events (they have their own lifecycle events that work as methods on the class itself).\n\n## Development vs Production modes\n\nBy default, Inferno will run in development mode. Development mode provides extra checks and better error messages at the cost of slower performance and larger code to parse.\nWhen using Inferno in a production environment, it is highly recommended that you turn off development mode.\n\n### Running Inferno on Node JS\n\nEnsure the environment variable `process.env.NODE_ENV` is set to `production`.\n\n## Application bundling\n\nWhen building your application bundle, ensure `process.env.NODE_ENV` is replaced with string`\"development\"` or `\"production\"` based on the workflow.\nIt is recommended to use [ts-plugin-inferno](https://github.com/infernojs/ts-plugin-inferno) for typescript TSX compilation and [babel-plugin-infeno](https://github.com/infernojs/babel-plugin-inferno) for javascript JSX compilation.\n\nWhen building for development, you may want to use `inferno.dev.mjs` for v9 or newer and `inferno.dev.esm.js` for older than v9. That bundle file contains ES6 exports for better tree-shaking support, improved error messages and added validation to help fixing possible issues during development.\nThe file is found from `package.json` - `dev:module` entry point and the files are physically located in `node_modules/inferno/dist/` folder.\nRemember that it is not recommended to use that file in production due to slower performance. For production usage use `node_modules/inferno/dist/inferno.mjs` -file for v9 or newer and `node_modules/inferno/dist/inferno.esm.js` -file for older than v9.\n\nExample of **Webpack** configuration:\n\n```js\nconst path = require('path');\nconst infernoTsx = require('ts-plugin-inferno').default;\n\n... webpack config ...\n\n    module: {\n        rules: [\n            {\n                test: /\\.js$/, // Add \"jsx\" if your application uses `jsx` file extensions\n                exclude: /node_modules/,\n                use: [{\n                    loader: 'babel-loader',\n                    options: {\n                        plugins: [\n                            // Compile javascript JSX syntax using inferno's own plugin\n                            ['babel-plugin-inferno', {imports: true}]\n                        ]\n                    }\n                }]\n            },\n            {\n                test: /\\.ts+(|x)$/, // Compile ts and tsx extensions\n                exclude: /node_modules/,\n                use: [{\n                    loader: 'ts-loader',\n                    options: {\n                        getCustomTransformers: () => ({\n                            // inferno custom TSX plugin\n                            after: [infernoTsx()]\n                        }),\n                        compilerOptions: {\n                            /* typescript compiler options */\n                        }\n                    }\n                }]\n            }\n        ]\n    },\n    resolve: {\n        extensions: ['.js', '.ts', '.tsx'],\n        alias: {\n            // This maps import \"inferno\" to es6 module entry based on workflow\n            inferno: path.resolve(__dirname, 'node_modules/inferno/dist', isProduction ? 'index.dev.mjs' : 'index.mjs')\n        }\n    },\n    plugins: [\n        new webpack.DefinePlugin({\n            'process.env': {\n                'NODE_ENV':  JSON.stringify(isProduction ? 'production' : 'development')\n            }\n        })\n    ]\n```\n\nExample of **Rollup** configuration:\n\n```js\nconst path = require('path');\nconst alias = require('@rollup/plugin-alias');\nconst {babel} = require('@rollup/plugin-babel');\nconst replace = require('@rollup/plugin-replace');\nconst typescript = require('rollup-plugin-typescript2');\nconst transformInferno = require('ts-plugin-inferno').default;\n\n... Rollup config ...\n{\n    input: /* entry file */,\n    plugins: [\n            alias({\n                resolve: ['.js'],\n                entries: [\n                    // This maps import \"inferno\" to es6 module entry based on workflow\n                    {find: 'inferno', replacement: path.resolve(__dirname, 'node_modules/inferno/dist', isProduction ? 'index.dev.mjs' : 'index.mjs')}\n                ]\n            }),\n            typescript({\n                include: ['*.ts+(|x)', '**/*.ts+(|x)'],\n                transformers: [\n                    () => ({\n                        after: [transformInferno()]\n                    })\n                ],\n                tsconfig: 'tsconfig.json',\n                tsconfigOverride: {\n                    /* typescript compiler options */\n                }\n            }),\n            babel({\n                babelrc: false,\n                sourceMaps: isDeploy,\n                plugins: [\n                    // Compile javascript JSX syntax using inferno's own plugin\n                    ['babel-plugin-inferno', {imports: true}]\n                ],\n                babelHelpers: 'bundled'\n            })\n    ]\n}\n```\n\n### Custom namespaces\n\nInferno always wants to deliver great performance. In order to do so, it has to make intelligent assumptions about the state of the DOM and the elements available to mutate. Custom namespaces conflict with this idea and change the schema of how different elements and attributes might work, so Inferno makes no attempt to support namespaces. Instead, SVG namespaces are automatically applied to elements and attributes based on their `tag name`.\n\n## Development\n\nIf you want to contribute code, fork this project and submit a PR from your fork. To run browser tests you need to build the repos. A complete rebuild of the repos can take >5 mins.\n\n```sh\n$ git clone git@github.com:infernojs/inferno.git\n$ cd inferno && npm i\n$ npm run test:node\n$ npm run build\n$ npm run test:browser\n```\n\nIf you only want to run the browser tests when coding, use the following to reduce turnaround by 50-80%:\n\n```sh\n$ npm run quick-test:browser # Compiles all packages and runs browser tests\n$ npm run quick-test:browser-inferno # Only compiles the inferno package and runs browser tests\n$ npm run quick-test:browser-debug # Compiles all packages and runs browser tests with \"debug\"\n```\n\n## Community\n\nThere is an InfernoJS Discord. You can join via [https://discord.gg/SUKuhgaBpF](https://discord.gg/SUKuhgaBpF).\n\n### Contributors\n\nThis project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].\n<a href=\"https://github.com/infernojs/inferno/graphs/contributors\"><img src=\"https://opencollective.com/inferno/contributors.svg?width=890\" /></a>\n\n### Backers\n\nThank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/inferno#backer)]\n\n<a href=\"https://opencollective.com/inferno#backers\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/backers.svg?width=890\"></a>\n\n### Sponsors\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/inferno#sponsor)]\n\n<a href=\"https://opencollective.com/inferno/sponsor/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/4/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/inferno/sponsor/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/inferno/sponsor/9/avatar.svg\"></a>\n"
  },
  {
    "path": "packages/inferno/__tests__/animationHooks.spec.tsx",
    "content": "import { Component, type InfernoNode, render } from 'inferno';\n\ndescribe('animation hooks', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  /**\n   * This is how component animation hooks work:\n   *\n   * On node creation, if there is a callback, a reference to the DOM-node is passed to that callback which allows for CSS-\n   * animations to be applied.\n   *\n   * On node removal, if there is a callback, the node isn't actually removed until the callback has finished.\n   *\n   * On node move, if there is a callback, the original node is cloned and both a reference to the cloned node and the new\n   * node are passed to the callback allowing CSS-animations to be performed.\n   *\n   * ** Entrypoints **\n   * - mounting.ts\n   * - unmounnting.ts\n   *\n   * ** Scope **\n   * We will start by implementing this for class components. Animations are expensive so it is probably a reasonable\n   * tradeoff to force the use of class componnents.\n   *\n   * QUESTION: How do we handle nested animations?\n   * Normally we only want to animated the outermost animation, but there are situation when the dev might want to\n   * do this differenty. Should we:\n   * - always block animations in children?\n   * - allow the dev to specify?\n   *\n   * Ex. you have a page animation and also animations on items in that page.\n   * ANSWER: I will block all animations down stream for starters. Giving an option requires A LOT of thought on\n   * edge cases.\n   *\n   * QUESTION: What if we add a set of siblings in a list, then all of them should animate, no?\n   * DONE: Investigate how to solve this.\n   * ANSWER: Animations should be a tree and only the highest node animates, but all siblings will animate\n   *\n   * DONE: Fix code path when removing last item in a list using clearDOM(dom) optmisation\n   * DONE: The callback is lost when transition is completed by the timeout\n   * QUESTION: Should I require the component to have a key?\n   * ANSWER: No, they should only be required in lists.\n   * DONE: What happens if order of DOM is changed during animation?\n   * DONE: remove intermediate elements during animation in list\n   * DONE: randomly reassign keys in a list (before/during animation)\n   * DONE: randomly sort list during animation\n   * DONE: shuffle keys\n   * DONE: The keyed patching appears to add children despite existing nodes with same key\n   * DONE: When rerendering a list 1,3,4,5,6 to 1,2,3,4,5 there are issues in the patching algorithm where 6 is left in DOM\n   * STARTED: Compare with tests in patchKeyedChildren.spec.js\n   * TODO: Investigate adding animations in https://github.com/infernojs/inferno/tree/master/docs/uibench-reactlike\n   * TODO: Add an animation blocking parent component to example\n   *\n   */\n\n  it('should NOT call \"componentWillMove\" when component is inserted into DOM', () => {\n    const spyer = jasmine.createSpy();\n    class App extends Component {\n      public componentWillMove() {\n        spyer('willMove');\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    render(<App />, container);\n\n    expect(spyer).toHaveBeenCalledTimes(1);\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n  });\n  it('should NOT call \"componentWillMove\" when component is removed from DOM', () => {\n    const spyer = jasmine.createSpy();\n    class App extends Component {\n      public componentWillMove() {\n        spyer('willMove');\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    render(<App />, container);\n\n    render(null, container);\n\n    expect(spyer).toHaveBeenCalledTimes(1);\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n  });\n\n  it('should call \"componentWillMove\" when component is about to be moved in DOM', () => {\n    const spyer = jasmine.createSpy();\n    class App extends Component {\n      public componentWillMove() {\n        spyer('willMove');\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    render(\n      <div>\n        <App key=\"1\">1</App>\n        <App key=\"2\">2</App>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toEqual('12');\n\n    render(\n      <div>\n        <App key=\"2\">2</App>\n        <App key=\"1\">1</App>\n      </div>,\n      container,\n    );\n\n    expect(container.textContent).toEqual('21');\n    // Only the first element needs to perform a DOM move\n    // The second element is animated by parent checking positions before and after move\n    expect(spyer).toHaveBeenCalledTimes(3);\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(2)).toEqual(['willMove']);\n  });\n\n  it('should call \"componentWillMove\" when component is about to be moved in DOM', () => {\n    const spyer = jasmine.createSpy();\n\n    class App extends Component<unknown, unknown> {\n      public componentWillMove(_parentVNode, _parent, dom) {\n        spyer('willMove');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    render(\n      <div>\n        <App key=\"1\">1</App>\n        <App key=\"2\">2</App>\n        <App key=\"3\">3</App>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toEqual('123');\n\n    render(\n      <div>\n        <App key=\"2\">2</App>\n        <App key=\"3\">3</App>\n        <App key=\"1\">1</App>\n      </div>,\n      container,\n    );\n\n    expect(container.textContent).toEqual('231');\n    // Only the first element needs to perform a DOM move\n    // The second element is animated by parent checking positions before and after move\n    expect(spyer).toHaveBeenCalledTimes(4);\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(2)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(3)).toEqual(['willMove']);\n  });\n\n  it('should call \"componentWillMove\" when component is about to be moved in DOM', () => {\n    const spyer = jasmine.createSpy();\n    let parentDom;\n    class App extends Component {\n      public componentWillMove(_parentVNode, parent, dom) {\n        spyer('willMove');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n        parentDom = parentDom || parent;\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    render(\n      <div>\n        <App key=\"1\">1</App>\n        <App key=\"2\">2</App>\n        <App key=\"3\">3</App>\n        <App key=\"4\">4</App>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toEqual('1234');\n\n    render(\n      <div>\n        <App key=\"4\">4</App>\n        <App key=\"3\">3</App>\n        <App key=\"2\">2</App>\n        <App key=\"1\">1</App>\n      </div>,\n      container,\n    );\n\n    expect(spyer).toHaveBeenCalledTimes(7);\n    // Three elements need to perform a DOM move\n    // The fourth element is animated by parent checking positions before and after move\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(2)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(3)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(4)).toEqual(['willMove']);\n    expect(spyer.calls.argsFor(5)).toEqual(['willMove']);\n    expect(spyer.calls.argsFor(6)).toEqual(['willMove']);\n    expect(container.textContent).toEqual('4321');\n  });\n\n  it('should call \"componentDidAppear\" when component has been inserted into DOM', () => {\n    const spyer = jasmine.createSpy();\n    class App extends Component {\n      public componentDidAppear(dom) {\n        spyer('didAppear');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    render(<App />, container);\n\n    expect(spyer).toHaveBeenCalledTimes(2);\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['didAppear']);\n  });\n\n  it('should only call parent \"componentDidAppear\" when component tree has been inserted into DOM', () => {\n    const spyer = jasmine.createSpy();\n    class Child extends Component {\n      public componentDidAppear() {\n        spyer('no-op');\n      }\n\n      public componentDidMount() {\n        spyer('childDidMount');\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    class App extends Component {\n      public componentDidAppear(dom) {\n        spyer('didAppear');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return (\n          <div>\n            <Child />\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    expect(spyer).toHaveBeenCalledTimes(3);\n    expect(spyer.calls.argsFor(0)).toEqual(['childDidMount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(2)).toEqual(['didAppear']);\n  });\n\n  it('should only call \"componentDidAppear\" when child component has been inserted into DOM', (done) => {\n    const spyer = jasmine.createSpy();\n    class Child extends Component {\n      public componentDidAppear() {\n        spyer('childDidAppear');\n      }\n\n      public componentDidMount() {\n        spyer('childDidMount');\n      }\n\n      public render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    interface AppState {\n      items: number[];\n    }\n\n    class App extends Component<unknown, AppState> {\n      public state: AppState;\n\n      constructor() {\n        super(...arguments);\n        this.state = {\n          items: [1],\n        };\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n        setTimeout(() => {\n          this.setState({\n            items: [1, 2],\n          });\n          // Make sure inferno is done and then check the results\n          setTimeout(finished, 5);\n        }, 5);\n      }\n\n      public render() {\n        return (\n          <div>\n            {this.state.items.map((i) => (\n              <Child key={i}>{i}</Child>\n            ))}\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    const finished = () => {\n      expect(spyer).toHaveBeenCalledTimes(5);\n      expect(spyer.calls.argsFor(0)).toEqual(['childDidMount']);\n      expect(spyer.calls.argsFor(1)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(2)).toEqual(['childDidAppear']);\n      expect(spyer.calls.argsFor(3)).toEqual(['childDidMount']);\n      expect(spyer.calls.argsFor(4)).toEqual(['childDidAppear']);\n      expect(container.innerHTML).toEqual(\n        '<div><div>1</div><div>2</div></div>',\n      );\n      done();\n    };\n  });\n\n  it('should call all \"componentDidAppear\" when multiple siblings have been inserted into DOM', () => {\n    const spyer = jasmine.createSpy();\n    class Child extends Component {\n      public componentDidAppear(dom) {\n        spyer('childDidAppear');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    class App extends Component {\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return (\n          <div>\n            <Child />\n            <Child />\n            <Child />\n            <Child />\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    expect(spyer).toHaveBeenCalledTimes(5);\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['childDidAppear']);\n    expect(spyer.calls.argsFor(2)).toEqual(['childDidAppear']);\n    expect(spyer.calls.argsFor(3)).toEqual(['childDidAppear']);\n    expect(spyer.calls.argsFor(4)).toEqual(['childDidAppear']);\n  });\n\n  it('should call \"componentWillDisappear\" when component is about to be removed from DOM', () => {\n    const spyer = jasmine.createSpy();\n    class App extends Component {\n      public componentWillDisappear(dom, done) {\n        spyer('willDisappear');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n        expect(done instanceof Function).toEqual(true);\n        done();\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    render(<App />, container);\n\n    render(null, container);\n\n    expect(spyer).toHaveBeenCalledTimes(2);\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['willDisappear']);\n  });\n\n  it('should handle async callbacks from \"componentWillDisappear\"', (done) => {\n    const spyer = jasmine.createSpy();\n    class App extends Component {\n      public componentWillDisappear(dom, callback) {\n        spyer('willDisappear');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n        expect(callback instanceof Function).toEqual(true);\n        setTimeout(() => {\n          callback();\n          setTimeout(() => {\n            didFinish();\n          }, 10);\n        }, 10);\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    render(<App />, container);\n\n    render(null, container);\n\n    function didFinish() {\n      expect(spyer).toHaveBeenCalledTimes(2);\n      expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(1)).toEqual(['willDisappear']);\n      done();\n    }\n  });\n\n  it('should handle async callbacks \"componentWillDisappear\" when removing the two last elements in list', (done) => {\n    /**\n     * This test is hard to get to consistently fail. It should trigger\n     * clearDOM from last animation callback prior to deferComponentClassRemoval\n     * of at least one item. But it does work as expected now\n     * Change\n     * clearVNodeDOM(vNode, parentDOM, true);\n     * to\n     * clearVNodeDOM(vNode, parentDOM, false);\n     * in\n     * function deferComponentClassRemoval\n     * to force failure\n     */\n    const spyer = jasmine.createSpy();\n    class App extends Component {\n      public state = {\n        items: [\n          0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n        ],\n      };\n\n      public render() {\n        if (this.state.items.length > 0) {\n          setTimeout(() => {\n            const items = this.state.items;\n            items.pop();\n            this.setState({ items });\n          });\n        }\n\n        if (this.state.items.length === 0) {\n          return <div />;\n        }\n\n        return (\n          <div>\n            {this.state.items.map((i) => (\n              <Item key={i} index={i} />\n            ))}\n          </div>\n        );\n      }\n    }\n\n    interface ItemProps {\n      index: number;\n    }\n\n    class Item extends Component<ItemProps> {\n      public componentWillDisappear(_dom, callback) {\n        spyer('willDisappear ' + this.props.index);\n\n        let timeout = 10;\n        if (this.props.index === 0) {\n          timeout = 0;\n        }\n        setTimeout(() => {\n          callback();\n        }, timeout);\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    render(<App />, container);\n\n    const checkRenderComplete_ONE = () => {\n      if (container.innerHTML !== '<div></div>') {\n        setTimeout(checkRenderComplete_ONE, 10);\n        return;\n      }\n      expect(spyer).toHaveBeenCalledTimes(40);\n      expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(19)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(20)).toEqual(['willDisappear 19']);\n      expect(spyer.calls.argsFor(39)).toEqual(['willDisappear 0']);\n      done();\n    };\n    checkRenderComplete_ONE();\n  });\n\n  it('should handle async callbacks from \"componentWillDisappear\" and mounting components with \"componentDidAppear\"', (done) => {\n    const spyer = jasmine.createSpy();\n    // Always call the componentWillDisappear callback after last render\n    let lastRenderDone = false;\n    let callMeAfterLastRender;\n\n    interface AppProps {\n      forceDone?: boolean;\n    }\n\n    class App extends Component<AppProps> {\n      public componentDidAppear(dom) {\n        spyer('didAppear');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n      }\n\n      public componentWillDisappear(dom, callback) {\n        spyer('willDisappear');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n        expect(callback instanceof Function).toEqual(true);\n\n        if (this.props.forceDone) {\n          callback();\n        } else {\n          setTimeout(() => {\n            callMeAfterLastRender = () => {\n              callback();\n              setTimeout(() => {\n                didFinish();\n              }, 10);\n            };\n            if (lastRenderDone) {\n              callMeAfterLastRender();\n            }\n          }, 10);\n        }\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    render(<App />, container);\n    render(null, container);\n    // forceDone completes the willDissapear hook immediately\n    render(<App forceDone />, container);\n\n    expect(container.innerHTML).toBe('<div></div><div></div>');\n\n    lastRenderDone = true;\n    callMeAfterLastRender?.();\n\n    function didFinish() {\n      expect(spyer).toHaveBeenCalledTimes(5);\n      expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(1)).toEqual(['didAppear']);\n      expect(spyer.calls.argsFor(2)).toEqual(['willDisappear']);\n      expect(spyer.calls.argsFor(3)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(4)).toEqual(['didAppear']);\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(null, container);\n      expect(container.innerHTML).toBe('');\n      done();\n    }\n  });\n\n  it('should handle async callbacks even when parent is removed during animation', (done) => {\n    const spyer = jasmine.createSpy();\n    class App extends Component {\n      public componentWillDisappear(dom, callback) {\n        spyer('willDisappear');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n        expect(callback instanceof Function).toEqual(true);\n        setTimeout(() => {\n          callback();\n        }, 10);\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    render(\n      <div>\n        <App />\n        <App />\n      </div>,\n      container,\n    );\n    render(\n      <div>\n        <App />\n      </div>,\n      container,\n    );\n    render(null, container);\n\n    expect(container.innerHTML).not.toEqual('');\n    // Wait for all async operations to finish\n    const checkRenderComplete_ONE = () => {\n      if (container.innerHTML !== '') {\n        setTimeout(checkRenderComplete_ONE, 10);\n        return;\n      }\n      expect(spyer).toHaveBeenCalledTimes(6);\n      expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(1)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(2)).toEqual(['willDisappear']);\n      expect(spyer.calls.argsFor(3)).toEqual(['willDisappear']);\n      expect(spyer.calls.argsFor(4)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(5)).toEqual(['willDisappear']);\n      done();\n    };\n    checkRenderComplete_ONE();\n  });\n\n  const template = function (child) {\n    return <div>{child}</div>;\n  };\n\n  it('should add all nodes', () => {\n    const spyer = jasmine.createSpy();\n\n    render(template(generateKeyNodes([], spyer)), container);\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    // expect(spyer).toHaveBeenCalledTimes(4);\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n    // expect(spyer).toHaveBeenCalledTimes(8);\n  });\n\n  it('should size up', () => {\n    const spyer = jasmine.createSpy();\n    render(template(generateKeyNodes(['#0', '#1'], spyer)), container);\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    // expect(spyer).toHaveBeenCalledTimes(4);\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n    // expect(spyer).toHaveBeenCalledTimes(8);\n  });\n\n  it('should do smiple size down', () => {\n    const spyer = jasmine.createSpy();\n    render(template(generateKeyNodes(['#0', '#1', '#2'], spyer)), container);\n    render(template(generateKeyNodes(['#0', '#2'], spyer)), container);\n    expect(container.textContent).toBe('#0#2');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    // expect(spyer).toHaveBeenCalledTimes(4);\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n    // expect(spyer).toHaveBeenCalledTimes(8);\n  });\n\n  it('should size down', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    render(template(generateKeyNodes(['#0', '#1'], spyer)), container);\n    // expect(spyer).toHaveBeenCalledTimes(2);\n    expect(container.textContent).toBe('#0#1');\n    expect(container.firstChild.childNodes.length).toBe(2);\n\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    render(template(generateKeyNodes(['#0', '#1'], spyer)), container);\n\n    // expect(spyer).toHaveBeenCalledTimes(10);\n    expect(container.textContent).toBe('#0#1');\n    expect(container.firstChild.childNodes.length).toBe(2);\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n    // expect(spyer).toHaveBeenCalledTimes(12);\n  });\n\n  it('should handle multiple removes of siblings combined with adds', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3', '#4', '#5'], spyer)),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['#0', '#2', '#5', '#6'], spyer)),\n      container,\n    );\n    // expect(spyer).toHaveBeenCalledTimes(2);\n    expect(container.textContent).toBe('#0#2#5#6');\n    expect(container.firstChild.childNodes.length).toBe(4);\n\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    render(template(generateKeyNodes(['#10', '#11'], spyer)), container);\n\n    // expect(spyer).toHaveBeenCalledTimes(10);\n    expect(container.textContent).toBe('#10#11');\n    expect(container.firstChild.childNodes.length).toBe(2);\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n    // expect(spyer).toHaveBeenCalledTimes(12);\n  });\n\n  it('should clear all nodes', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    render(template(generateKeyNodes([], spyer)), container);\n    expect(container.textContent).toBe('');\n    expect(container.firstChild.childNodes.length).toBe(0);\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    render(template(generateKeyNodes([], spyer)), container);\n  });\n\n  it('should work with mixed nodes', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['1', '#0', '#1', '#2'], spyer)),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key for start to end', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['a', '#0', '#1', '#2'], spyer)),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', 'a'], spyer)),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2a');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['#0', 'a', '#2', '#3'], spyer)),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['#0', '#1', 'a', '#3'], spyer)),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1a#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  /* Skipping spyer from here on */\n\n  it('should move a key', () => {\n    render(template(generateKeyNodes(['#0', 'a', '#2', '#3'])), container);\n    render(template(generateKeyNodes(['#0', '#1', 'a', '#3'])), container);\n    expect(container.textContent).toBe('#0#1a#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key with a size up', () => {\n    render(template(generateKeyNodes(['a', '#1', '#2', '#3'])), container);\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3', 'a', '#5'])),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3a#5');\n    expect(container.firstChild.childNodes.length).toBe(6);\n  });\n  it('should move a key with a size down', () => {\n    render(template(generateKeyNodes(['a', '#1', '#2', '#3'])), container);\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    expect(container.textContent).toBe('#0a#2');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should avoid unnecessary reordering', () => {\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    expect(container.textContent).toBe('#0a#2');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should work with keyed nodes', () => {\n    render(template(generateKeyNodes([0, 1, 2, 3, 4])), container);\n    render(template(generateKeyNodes([1, 2, 3, 4, 0])), container);\n    expect(container.textContent).toBe('12340');\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([0, 1, 2, 3, 4])), container);\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    expect(container.textContent).toBe('#0a#2');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should reorder keys', () => {\n    render(\n      template(generateKeyNodes(['1', '2', '3', '4', 'abc', '6', 'def', '7'])),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n  });\n  it('should remove one key at the start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['b', 'c'])), container);\n    expect(container.textContent).toBe('bc');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should do a complex reverse', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    render(template(generateKeyNodes(['d', 'c', 'b', 'a'])), container);\n    expect(container.textContent).toBe('dcba');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should remove two keys at the start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['c'])), container);\n    expect(container.textContent).toBe('c');\n    expect(container.firstChild.childNodes.length).toBe(1);\n  });\n  it('should add one key to start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes(['a', 'b'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should add two key to start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes(['c'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should remove one key at the end', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['a', 'b'])), container);\n    expect(container.textContent).toBe('ab');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should remove two keys at the end', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['a'])), container);\n    expect(container.textContent).toBe('a');\n    expect(container.firstChild.childNodes.length).toBe(1);\n  });\n  it('should add one key at the end', () => {\n    render(template(generateKeyNodes(['a', 'b'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should add two key at the end', () => {\n    render(template(generateKeyNodes(['a'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should add to end, delete from center & reverse', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    render(template(generateKeyNodes(['e', 'd', 'c', 'a'])), container);\n    expect(container.textContent).toBe('edca');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should add to the beginning and remove', () => {\n    render(template(generateKeyNodes(['c', 'd'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c', 'e'])), container);\n    expect(container.textContent).toBe('abce');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should keep a central pivot', () => {\n    render(template(generateKeyNodes(['1', '2', '3'])), container);\n    render(template(generateKeyNodes(['4', '2', '5'])), container);\n    expect(container.textContent).toBe('425');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should insert to the middle', () => {\n    render(template(generateKeyNodes(['c', 'd', 'e'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'e'])), container);\n    expect(container.textContent).toBe('abe');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes(['c', 'd', 'e'])), container);\n    render(template(generateKeyNodes(['c', 'd', 'e'])), container);\n    render(template(generateKeyNodes(['a', 'p', 'e'])), container);\n    expect(container.textContent).toBe('ape');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should shuffle, insert and remove', () => {\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 'e', 'f', 'g'])),\n      container,\n    );\n    render(template(generateKeyNodes(['b', 'c', 'a'])), container);\n    expect(container.textContent).toBe('bca');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should remove a element from the middle', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([1, 2, 4, 5])), container);\n    expect(container.textContent).toBe('1245');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a element forward', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([2, 3, 1, 4])), container);\n    expect(container.textContent).toBe('2314');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([3, 2, 1, 4])), container);\n    expect(container.textContent).toBe('3214');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([3, 2, 4, 1])), container);\n    expect(container.textContent).toBe('3241');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  it('should move a element to the end', () => {\n    render(template(generateKeyNodes([1, 2, 3])), container);\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes([2, 3, 1])), container);\n    expect(container.textContent).toBe('231');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should move a element backwards', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([1, 4, 2, 3])), container);\n    expect(container.textContent).toBe('1423');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should swap first and last', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([4, 2, 3, 1])), container);\n    expect(container.textContent).toBe('4231');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  it('should move to left and replace', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([4, 1, 2, 3, 6])), container);\n    expect(container.textContent).toBe('41236');\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([4, 5, 2, 3, 0])), container);\n    expect(container.textContent).toBe('45230');\n    render(template(generateKeyNodes([1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(5);\n  });\n\n  it('should move to left and leave a hole', () => {\n    render(template(generateKeyNodes([1, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes([4, 6])), container);\n    expect(container.textContent).toBe('46');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should do something', () => {\n    render(template(generateKeyNodes([0, 1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(6);\n    render(template(generateKeyNodes([4, 3, 2, 1, 5, 0])), container);\n    expect(container.textContent).toBe('432150');\n    expect(container.firstChild.childNodes.length).toBe(6);\n  });\n\n  it('should cycle order correctly', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n    render(template(generateKeyNodes([2, 3, 4, 1])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('2341');\n    render(template(generateKeyNodes([3, 4, 1, 2])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('3412');\n    render(template(generateKeyNodes([4, 1, 2, 3])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('4123');\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n  });\n\n  it('should cycle order correctly in the other direction', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n    render(template(generateKeyNodes([4, 1, 2, 3])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('4123');\n    render(template(generateKeyNodes([3, 4, 1, 2])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('3412');\n    render(template(generateKeyNodes([2, 3, 4, 1])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('2341');\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n  });\n\n  it('should allow any character as a key', () => {\n    render(template(generateKeyNodes(['<WEIRD/&\\\\key>'])), container);\n    render(\n      template(\n        generateKeyNodes([\n          'INSANE/(/&\\\\key',\n          '<CRAZY/&\\\\key>',\n          '<WEIRD/&\\\\key>',\n        ]),\n      ),\n      container,\n    );\n    expect(container.textContent).toBe(\n      'INSANE/(/&\\\\key<CRAZY/&\\\\key><WEIRD/&\\\\key>',\n    );\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should reorder nodes', () => {\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n    render(\n      template(generateKeyNodes(['1', '2', '3', '4', 'abc', '6', 'def', '7'])),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n  });\n\n  it('should do a advanced shuffle - numbers and letters', () => {\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 1, 2, 3])),\n      container,\n    );\n    expect(container.textContent).toBe('abcd123');\n    expect(container.firstChild.childNodes.length).toBe(7);\n    render(\n      template(generateKeyNodes([1, 'e', 2, 'b', 'f', 'g', 'c', 'a', 3])),\n      container,\n    );\n    expect(container.textContent).toBe('1e2bfgca3');\n    expect(container.firstChild.childNodes.length).toBe(9);\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 1, 2, 3])),\n      container,\n    );\n    expect(container.textContent).toBe('abcd123');\n    expect(container.firstChild.childNodes.length).toBe(7);\n    render(\n      template(generateKeyNodes([0, 'e', 2, 'b', 'f', 'g', 'c', 'a', 4])),\n      container,\n    );\n    expect(container.textContent).toBe('0e2bfgca4');\n    expect(container.firstChild.childNodes.length).toBe(9);\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 1, 2, 3])),\n      container,\n    );\n    expect(container.textContent).toBe('abcd123');\n    expect(container.firstChild.childNodes.length).toBe(7);\n    render(\n      template(generateKeyNodes([1, 'e', 2, 'b', 'f', 'g', 'c', 'a', 3])),\n      container,\n    );\n    expect(container.textContent).toBe('1e2bfgca3');\n    expect(container.firstChild.childNodes.length).toBe(9);\n  });\n\n  it('should do a complex removal at the beginning', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes(['c', 'd'])), container);\n    expect(container.textContent).toBe('cd');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  it('should do move and sync nodes from right to left', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template(\n        generateKeyNodes(['c', 'l', 1, 2, 3, 4, 5, 6, 7, 8, 9, 'd', 'g', 'b']),\n      ),\n      container,\n    );\n    expect(container.textContent).toBe('cl123456789dgb');\n    expect(container.firstChild.childNodes.length).toBe(14);\n  });\n\n  describe('Should handle massive large arrays', () => {\n    let items;\n\n    beforeEach(function () {\n      items = new Array(1000);\n      for (let i = 0; i < 1000; i++) {\n        items[i] = i;\n      }\n    });\n\n    it('Should handle massive large arrays - initial', () => {\n      render(template(generateKeyNodes(items)), container);\n\n      expect(container.textContent).toEqual(items.join(''));\n    });\n\n    it('Should handle massive arrays shifting once by 2', () => {\n      items = items.concat(items.splice(0, 2));\n      render(template(generateKeyNodes(items)), container);\n\n      expect(container.textContent).toEqual(items.join(''));\n    });\n\n    for (let i = 0; i < 10; i++) {\n      it(\n        'Should handle massive arrays shifting ' + i + ' times by ' + i,\n        () => {\n          for (let j = 0; j < i; j++) {\n            items = items.concat(items.splice(i, j));\n          }\n          render(template(generateKeyNodes(items)), container);\n          expect(container.textContent).toEqual(items.join(''));\n        },\n      );\n    }\n  });\n\n  describe('Calendar like layout', () => {\n    interface AnimatedProps {\n      key: string;\n      children?: any;\n    }\n\n    class Animated extends Component<AnimatedProps, unknown> {\n      public componentDidAppear(_dom) {\n        // Trigger animation code paths on add\n      }\n\n      public componentWillDisappear(_dom, done) {\n        // Trigger animation code paths on remove\n        done();\n      }\n\n      public render({ children }: AnimatedProps) {\n        return <div>{children}</div>;\n      }\n    }\n\n    function o(text) {\n      return <Animated key={'o' + text}>{',o' + text}</Animated>;\n    }\n\n    function d(text) {\n      return <Animated key={'d' + text}>{',d' + text}</Animated>;\n    }\n\n    function wk(text) {\n      return <Animated key={'wk' + text}>{',wk' + text}</Animated>;\n    }\n\n    it('Should do complex suffle without duplications', () => {\n      const layout1 = [\n        wk(31),\n        d(1),\n        d(2),\n        d(3),\n        d(4),\n        d(5),\n        d(6),\n        d(7),\n        wk(32),\n        d(8),\n        d(9),\n        d(10),\n        d(11),\n        d(12),\n        d(13),\n        d(14),\n        wk(33),\n        d(15),\n        d(16),\n        d(17),\n        d(18),\n        d(19),\n        d(20),\n        d(21),\n        wk(34),\n        d(22),\n        d(23),\n        d(24),\n        d(25),\n        d(26),\n        d(27),\n        d(28),\n        wk(35),\n        d(29),\n        d(30),\n        d(31),\n        o(1),\n        o(2),\n        o(3),\n        o(4),\n        wk(36),\n        o(5),\n        o(6),\n        o(7),\n        o(8),\n        o(9),\n        o(10),\n        o(11),\n      ];\n      render(template(layout1), container);\n\n      expect(container.textContent).toBe(\n        ',wk31,d1,d2,d3,d4,d5,d6,d7,wk32,d8,d9,d10,d11,d12,d13,d14,wk33,d15,d16,d17,d18,d19,d20,d21,wk34,d22,d23,d24,d25,d26,d27,d28,wk35,d29,d30,d31,o1,o2,o3,o4,wk36,o5,o6,o7,o8,o9,o10,o11',\n      );\n\n      const layout2 = [\n        wk(35),\n        o(29),\n        o(30),\n        o(31),\n        d(1),\n        d(2),\n        d(3),\n        d(4),\n        wk(36),\n        d(5),\n        d(6),\n        d(7),\n        d(8),\n        d(9),\n        d(10),\n        d(11),\n        wk(37),\n        d(12),\n        d(13),\n        d(14),\n        d(15),\n        d(16),\n        d(17),\n        d(18),\n        wk(38),\n        d(19),\n        d(20),\n        d(21),\n        d(22),\n        d(23),\n        d(24),\n        d(25),\n        wk(39),\n        d(26),\n        d(27),\n        d(28),\n        d(29),\n        d(30),\n        o(1),\n        o(2),\n        wk(40),\n        o(3),\n        o(4),\n        o(5),\n        o(6),\n        o(7),\n        o(8),\n        o(9),\n      ];\n      render(template(layout2), container);\n\n      expect(container.textContent).toBe(\n        ',wk35,o29,o30,o31,d1,d2,d3,d4,wk36,d5,d6,d7,d8,d9,d10,d11,wk37,d12,d13,d14,d15,d16,d17,d18,wk38,d19,d20,d21,d22,d23,d24,d25,wk39,d26,d27,d28,d29,d30,o1,o2,wk40,o3,o4,o5,o6,o7,o8,o9',\n      );\n    });\n  });\n});\n\nfunction factory(spyer?: jasmine.Spy) {\n  // TODO: Add componentWillMove\n  return class Animated extends Component<any, any> {\n    public componentDidAppear(_dom) {\n      if (spyer) {\n        spyer('didAppear');\n      }\n    }\n\n    public componentWillDisappear(_dom, done) {\n      if (spyer) {\n        spyer('willDisappear');\n      }\n\n      done();\n    }\n\n    public render({ children }) {\n      return <div>{children}</div>;\n    }\n  };\n}\n\nfunction generateKeyNodes(array: Array<string | number>, spyer?) {\n  let id: string | number;\n  let key: string | number;\n  const children: InfernoNode[] = [];\n  let newKey: string | number | null;\n  const Tag = factory(spyer);\n\n  for (let i = 0; i < array.length; i++) {\n    id = key = array[i];\n    if (key !== null && (typeof key !== 'string' || key[0] !== '#')) {\n      newKey = key;\n    } else {\n      newKey = null;\n    }\n\n    children.push(\n      <Tag key={newKey} id={String(id)}>\n        {id}\n      </Tag>,\n    );\n  }\n  return children;\n}\n"
  },
  {
    "path": "packages/inferno/__tests__/animationHooksFunc.spec.tsx",
    "content": "import {\n  Component,\n  type InfernoNode,\n  type InfernoSingleNode,\n  render,\n} from 'inferno';\n\ndescribe('animation hooks', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should call \"onComponentDidAppear\" when component has been inserted into DOM', () => {\n    const spyer = jasmine.createSpy();\n\n    const Animated = () => {\n      return <div />;\n    };\n\n    const onComponentDidAppear = (dom, props) => {\n      spyer('didAppear');\n      expect(dom instanceof HTMLDivElement).toEqual(true);\n      expect(typeof props === 'object').toEqual(true);\n    };\n\n    class App extends Component {\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return <Animated onComponentDidAppear={onComponentDidAppear} />;\n      }\n    }\n\n    render(<App />, container);\n\n    expect(spyer).toHaveBeenCalledTimes(2);\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['didAppear']);\n  });\n\n  it('should only call parent \"onComponentDidAppear\" when component tree has been inserted into DOM', () => {\n    const spyer = jasmine.createSpy();\n\n    const Child = () => {\n      return <div />;\n    };\n\n    const childOnComponentDidAppear = (dom) => {\n      spyer('no-op');\n      expect(dom instanceof HTMLDivElement).toEqual(true);\n    };\n\n    const Parent = () => {\n      return <Child onComponentDidAppear={childOnComponentDidAppear} />;\n    };\n\n    const parentOnComponentDidAppear = (dom) => {\n      spyer('didAppear');\n      expect(dom instanceof HTMLDivElement).toEqual(true);\n    };\n\n    class App extends Component {\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return (\n          <div>\n            <Parent onComponentDidAppear={parentOnComponentDidAppear} />\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    expect(spyer).toHaveBeenCalledTimes(2);\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['didAppear']);\n  });\n\n  it('should only call \"componentDidAppear\" when child component has been inserted into DOM', (done) => {\n    const spyer = jasmine.createSpy();\n\n    const Child = (props) => {\n      return <div>{props.children}</div>;\n    };\n\n    const childOnComponentDidMount = () => {\n      spyer('childDidMount');\n    };\n\n    const childOnComponentDidAppear = () => {\n      spyer('childDidAppear');\n    };\n\n    interface AppState {\n      items: number[];\n    }\n\n    class App extends Component<unknown, AppState> {\n      public state: AppState;\n\n      constructor() {\n        super(...arguments);\n        this.state = {\n          items: [1],\n        };\n      }\n\n      public componentDidMount() {\n        spyer('didMount');\n        setTimeout(() => {\n          this.setState({\n            items: [1, 2],\n          });\n          // Make sure inferno is done and then check the results\n          setTimeout(finished, 5);\n        }, 5);\n      }\n\n      public render() {\n        return (\n          <div>\n            {this.state.items.map((i) => (\n              <Child\n                key={i}\n                onComponentDidAppear={childOnComponentDidAppear}\n                onComponentDidMount={childOnComponentDidMount}\n              >\n                {i}\n              </Child>\n            ))}\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    const finished = () => {\n      expect(spyer).toHaveBeenCalledTimes(5);\n      expect(spyer.calls.argsFor(0)).toEqual(['childDidMount']);\n      expect(spyer.calls.argsFor(1)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(2)).toEqual(['childDidAppear']);\n      expect(spyer.calls.argsFor(3)).toEqual(['childDidMount']);\n      expect(spyer.calls.argsFor(4)).toEqual(['childDidAppear']);\n      expect(container.innerHTML).toEqual(\n        '<div><div>1</div><div>2</div></div>',\n      );\n      done();\n    };\n  });\n\n  it('should call all \"componentDidAppear\" when multiple siblings have been inserted into DOM', () => {\n    const spyer = jasmine.createSpy();\n\n    const Child = () => {\n      return <div />;\n    };\n\n    const onComponentDidAppear = (dom) => {\n      spyer('childDidAppear');\n      expect(dom instanceof HTMLDivElement).toEqual(true);\n    };\n\n    class App extends Component {\n      public componentDidMount() {\n        spyer('didMount');\n      }\n\n      public render() {\n        return (\n          <div>\n            <Child onComponentDidAppear={onComponentDidAppear} />\n            <Child onComponentDidAppear={onComponentDidAppear} />\n            <Child onComponentDidAppear={onComponentDidAppear} />\n            <Child onComponentDidAppear={onComponentDidAppear} />\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    expect(spyer).toHaveBeenCalledTimes(5);\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['childDidAppear']);\n    expect(spyer.calls.argsFor(2)).toEqual(['childDidAppear']);\n    expect(spyer.calls.argsFor(3)).toEqual(['childDidAppear']);\n    expect(spyer.calls.argsFor(4)).toEqual(['childDidAppear']);\n  });\n\n  it('should call \"componentWillDisappear\" when component is about to be removed from DOM', () => {\n    const spyer = jasmine.createSpy();\n    const App = () => {\n      return <div />;\n    };\n\n    const onComponentWillDisappear = (dom, props, callback) => {\n      spyer('willDisappear');\n      expect(dom instanceof HTMLDivElement).toEqual(true);\n      expect(callback instanceof Function).toEqual(true);\n      expect(typeof props === 'object').toEqual(true);\n      callback();\n    };\n\n    const onComponentDidMount = () => {\n      spyer('didMount');\n    };\n\n    render(\n      <App\n        onComponentWillDisappear={onComponentWillDisappear}\n        onComponentDidMount={onComponentDidMount}\n      />,\n      container,\n    );\n\n    render(null, container);\n\n    expect(spyer).toHaveBeenCalledTimes(2);\n    expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['willDisappear']);\n  });\n\n  it('should handle async callbacks from \"componentWillDisappear\"', (done) => {\n    const spyer = jasmine.createSpy();\n\n    const App = () => {\n      return <div />;\n    };\n\n    const onComponentWillDisappear = (dom, _props, callback) => {\n      spyer('willDisappear');\n      expect(dom instanceof HTMLDivElement).toEqual(true);\n      expect(callback instanceof Function).toEqual(true);\n      setTimeout(() => {\n        callback();\n        setTimeout(() => {\n          didFinish();\n        }, 10);\n      }, 10);\n    };\n\n    const onComponentDidMount = () => {\n      spyer('didMount');\n    };\n\n    render(\n      <App\n        onComponentWillDisappear={onComponentWillDisappear}\n        onComponentDidMount={onComponentDidMount}\n      />,\n      container,\n    );\n\n    render(null, container);\n\n    function didFinish() {\n      expect(spyer).toHaveBeenCalledTimes(2);\n      expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(1)).toEqual(['willDisappear']);\n      done();\n    }\n  });\n\n  it('should handle async callbacks \"componentWillDisappear\" when removing the two last elements in list', (done) => {\n    /**\n     * This test is hard to get to consistently fail. It should trigger\n     * clearDOM from last animation callback prior to deferComponentClassRemoval\n     * of at least one item. But it does work as expected now\n     * Change\n     * clearVNodeDOM(vNode, parentDOM, true);\n     * to\n     * clearVNodeDOM(vNode, parentDOM, false);\n     * in\n     * function deferComponentClassRemoval\n     * to force failure\n     */\n    const spyer = jasmine.createSpy();\n\n    const Item = () => {\n      return <div />;\n    };\n\n    const getOnComponentWillDisappear = (index) => {\n      return (_dom, _props, callback) => {\n        spyer('willDisappear ' + index);\n\n        let timeout = 10;\n        if (index === 0) {\n          timeout = 0;\n        }\n        setTimeout(() => {\n          callback();\n        }, timeout);\n      };\n    };\n\n    const onComponentDidMount = () => {\n      spyer('didMount');\n    };\n\n    class App extends Component {\n      public state = {\n        items: [\n          0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n        ],\n      };\n\n      public render() {\n        if (this.state.items.length > 0) {\n          setTimeout(() => {\n            const items = this.state.items;\n            items.pop();\n            this.setState({ items });\n          });\n        }\n\n        if (this.state.items.length === 0) {\n          return <div />;\n        }\n\n        return (\n          <div>\n            {this.state.items.map((i) => (\n              <Item\n                key={i}\n                onComponentWillDisappear={getOnComponentWillDisappear(i)}\n                onComponentDidMount={onComponentDidMount}\n              />\n            ))}\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    const checkRenderComplete_ONE = () => {\n      if (container.innerHTML !== '<div></div>') {\n        setTimeout(checkRenderComplete_ONE, 100);\n        return;\n      }\n      expect(spyer).toHaveBeenCalledTimes(40);\n      expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(19)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(20)).toEqual(['willDisappear 19']);\n      expect(spyer.calls.argsFor(39)).toEqual(['willDisappear 0']);\n      done();\n    };\n    checkRenderComplete_ONE();\n  });\n\n  it('should handle async callbacks from \"componentWillDisappear\" and mounting components with \"componentDidAppear\"', (done) => {\n    const spyer = jasmine.createSpy();\n    // Always call the componentWillDisappear callback after last render\n    let lastRenderDone = false;\n    let callMeAfterLastRender;\n\n    const App = () => {\n      return <div />;\n    };\n\n    const onComponentDidAppear = (dom) => {\n      spyer('didAppear');\n      expect(dom instanceof HTMLDivElement).toEqual(true);\n    };\n\n    const getOnComponentWillDisappear =\n      (forceDone) => (dom, _props, callback) => {\n        spyer('willDisappear');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n        expect(callback instanceof Function).toEqual(true);\n\n        if (forceDone) {\n          callback();\n        } else {\n          setTimeout(() => {\n            callMeAfterLastRender = () => {\n              callback();\n              setTimeout(() => {\n                didFinish();\n              }, 10);\n            };\n            if (lastRenderDone) {\n              callMeAfterLastRender();\n            }\n          }, 10);\n        }\n      };\n\n    const onComponentDidMount = () => {\n      spyer('didMount');\n    };\n\n    render(\n      <App\n        onComponentDidAppear={onComponentDidAppear}\n        onComponentDidMount={onComponentDidMount}\n        onComponentWillDisappear={getOnComponentWillDisappear(false)}\n      />,\n      container,\n    );\n    render(null, container);\n    // forceDone completes the willDissapear hook immediately\n    render(\n      <App\n        onComponentDidAppear={onComponentDidAppear}\n        onComponentDidMount={onComponentDidMount}\n        onComponentWillDisappear={getOnComponentWillDisappear(true)}\n      />,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div></div><div></div>');\n\n    lastRenderDone = true;\n    callMeAfterLastRender?.();\n\n    function didFinish() {\n      expect(spyer).toHaveBeenCalledTimes(5);\n      expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(1)).toEqual(['didAppear']);\n      expect(spyer.calls.argsFor(2)).toEqual(['willDisappear']);\n      expect(spyer.calls.argsFor(3)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(4)).toEqual(['didAppear']);\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(null, container);\n      expect(container.innerHTML).toBe('');\n      done();\n    }\n  });\n\n  it('should handle async callbacks even when parent is removed during animation', (done) => {\n    const spyer = jasmine.createSpy();\n    const App = () => {\n      return <div />;\n    };\n\n    const onComponentWillDisappear = (dom, _props, callback) => {\n      spyer('willDisappear');\n      expect(dom instanceof HTMLDivElement).toEqual(true);\n      expect(callback instanceof Function).toEqual(true);\n      setTimeout(() => {\n        callback();\n      }, 10);\n    };\n\n    const onComponentDidMount = () => {\n      spyer('didMount');\n    };\n\n    render(\n      <div>\n        <App\n          onComponentDidMount={onComponentDidMount}\n          onComponentWillDisappear={onComponentWillDisappear}\n        />\n        <App\n          onComponentDidMount={onComponentDidMount}\n          onComponentWillDisappear={onComponentWillDisappear}\n        />\n      </div>,\n      container,\n    );\n    render(\n      <div>\n        <App\n          onComponentDidMount={onComponentDidMount}\n          onComponentWillDisappear={onComponentWillDisappear}\n        />\n      </div>,\n      container,\n    );\n    render(null, container);\n\n    expect(container.innerHTML).not.toEqual('');\n    // Wait for all async operations to finish\n    const checkRenderComplete_ONE = () => {\n      if (container.innerHTML !== '') {\n        setTimeout(checkRenderComplete_ONE, 10);\n        return;\n      }\n      expect(spyer).toHaveBeenCalledTimes(6);\n      expect(spyer.calls.argsFor(0)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(1)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(2)).toEqual(['willDisappear']);\n      expect(spyer.calls.argsFor(3)).toEqual(['willDisappear']);\n      expect(spyer.calls.argsFor(4)).toEqual(['didMount']);\n      expect(spyer.calls.argsFor(5)).toEqual(['willDisappear']);\n      done();\n    };\n    checkRenderComplete_ONE();\n  });\n\n  it('should call \"willMove\" when component is about to be moved to another part of DOM', () => {});\n\n  const template = function (child) {\n    return <div>{child}</div>;\n  };\n\n  it('should add all nodes', () => {\n    const spyer = jasmine.createSpy();\n\n    render(template(generateKeyNodes([], spyer)), container);\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    // expect(spyer).toHaveBeenCalledTimes(4);\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n    // expect(spyer).toHaveBeenCalledTimes(8);\n  });\n\n  it('should size up', () => {\n    const spyer = jasmine.createSpy();\n    render(template(generateKeyNodes(['#0', '#1'], spyer)), container);\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    // expect(spyer).toHaveBeenCalledTimes(4);\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n    // expect(spyer).toHaveBeenCalledTimes(8);\n  });\n\n  it('should do smiple size down', () => {\n    const spyer = jasmine.createSpy();\n    render(template(generateKeyNodes(['#0', '#1', '#2'], spyer)), container);\n    render(template(generateKeyNodes(['#0', '#2'], spyer)), container);\n    expect(container.textContent).toBe('#0#2');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    // expect(spyer).toHaveBeenCalledTimes(4);\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n    // expect(spyer).toHaveBeenCalledTimes(8);\n  });\n\n  it('should size down', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    render(template(generateKeyNodes(['#0', '#1'], spyer)), container);\n    // expect(spyer).toHaveBeenCalledTimes(2);\n    expect(container.textContent).toBe('#0#1');\n    expect(container.firstChild.childNodes.length).toBe(2);\n\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    render(template(generateKeyNodes(['#0', '#1'], spyer)), container);\n\n    // expect(spyer).toHaveBeenCalledTimes(10);\n    expect(container.textContent).toBe('#0#1');\n    expect(container.firstChild.childNodes.length).toBe(2);\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n    // expect(spyer).toHaveBeenCalledTimes(12);\n  });\n\n  it('should handle multiple removes of siblings combined with adds', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3', '#4', '#5'], spyer)),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['#0', '#2', '#5', '#6'], spyer)),\n      container,\n    );\n    // expect(spyer).toHaveBeenCalledTimes(2);\n    expect(container.textContent).toBe('#0#2#5#6');\n    expect(container.firstChild.childNodes.length).toBe(4);\n\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    render(template(generateKeyNodes(['#10', '#11'], spyer)), container);\n\n    // expect(spyer).toHaveBeenCalledTimes(10);\n    expect(container.textContent).toBe('#10#11');\n    expect(container.firstChild.childNodes.length).toBe(2);\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n    // expect(spyer).toHaveBeenCalledTimes(12);\n  });\n\n  it('should clear all nodes', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    render(template(generateKeyNodes([], spyer)), container);\n    expect(container.textContent).toBe('');\n    expect(container.firstChild.childNodes.length).toBe(0);\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    render(template(generateKeyNodes([], spyer)), container);\n  });\n\n  it('should work with mixed nodes', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['1', '#0', '#1', '#2'], spyer)),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3'], spyer)),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key for start to end', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['a', '#0', '#1', '#2'], spyer)),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', 'a'], spyer)),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2a');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key', () => {\n    const spyer = jasmine.createSpy();\n    render(\n      template(generateKeyNodes(['#0', 'a', '#2', '#3'], spyer)),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['#0', '#1', 'a', '#3'], spyer)),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1a#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  /* Skipping spyer from here on */\n\n  it('should move a key', () => {\n    render(template(generateKeyNodes(['#0', 'a', '#2', '#3'])), container);\n    render(template(generateKeyNodes(['#0', '#1', 'a', '#3'])), container);\n    expect(container.textContent).toBe('#0#1a#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key with a size up', () => {\n    render(template(generateKeyNodes(['a', '#1', '#2', '#3'])), container);\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3', 'a', '#5'])),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3a#5');\n    expect(container.firstChild.childNodes.length).toBe(6);\n  });\n  it('should move a key with a size down', () => {\n    render(template(generateKeyNodes(['a', '#1', '#2', '#3'])), container);\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    expect(container.textContent).toBe('#0a#2');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should avoid unnecessary reordering', () => {\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    expect(container.textContent).toBe('#0a#2');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should work with keyed nodes', () => {\n    render(template(generateKeyNodes([0, 1, 2, 3, 4])), container);\n    render(template(generateKeyNodes([1, 2, 3, 4, 0])), container);\n    expect(container.textContent).toBe('12340');\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([0, 1, 2, 3, 4])), container);\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    expect(container.textContent).toBe('#0a#2');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should reorder keys', () => {\n    render(\n      template(generateKeyNodes(['1', '2', '3', '4', 'abc', '6', 'def', '7'])),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n  });\n  it('should remove one key at the start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['b', 'c'])), container);\n    expect(container.textContent).toBe('bc');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should do a complex reverse', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    render(template(generateKeyNodes(['d', 'c', 'b', 'a'])), container);\n    expect(container.textContent).toBe('dcba');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should remove two keys at the start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['c'])), container);\n    expect(container.textContent).toBe('c');\n    expect(container.firstChild.childNodes.length).toBe(1);\n  });\n  it('should add one key to start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes(['a', 'b'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should add two key to start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes(['c'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should remove one key at the end', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['a', 'b'])), container);\n    expect(container.textContent).toBe('ab');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should remove two keys at the end', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['a'])), container);\n    expect(container.textContent).toBe('a');\n    expect(container.firstChild.childNodes.length).toBe(1);\n  });\n  it('should add one key at the end', () => {\n    render(template(generateKeyNodes(['a', 'b'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should add two key at the end', () => {\n    render(template(generateKeyNodes(['a'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should add to end, delete from center & reverse', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    render(template(generateKeyNodes(['e', 'd', 'c', 'a'])), container);\n    expect(container.textContent).toBe('edca');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should add to the beginning and remove', () => {\n    render(template(generateKeyNodes(['c', 'd'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c', 'e'])), container);\n    expect(container.textContent).toBe('abce');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should keep a central pivot', () => {\n    render(template(generateKeyNodes(['1', '2', '3'])), container);\n    render(template(generateKeyNodes(['4', '2', '5'])), container);\n    expect(container.textContent).toBe('425');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should insert to the middle', () => {\n    render(template(generateKeyNodes(['c', 'd', 'e'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'e'])), container);\n    expect(container.textContent).toBe('abe');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes(['c', 'd', 'e'])), container);\n    render(template(generateKeyNodes(['c', 'd', 'e'])), container);\n    render(template(generateKeyNodes(['a', 'p', 'e'])), container);\n    expect(container.textContent).toBe('ape');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should shuffle, insert and remove', () => {\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 'e', 'f', 'g'])),\n      container,\n    );\n    render(template(generateKeyNodes(['b', 'c', 'a'])), container);\n    expect(container.textContent).toBe('bca');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should remove a element from the middle', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([1, 2, 4, 5])), container);\n    expect(container.textContent).toBe('1245');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a element forward', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([2, 3, 1, 4])), container);\n    expect(container.textContent).toBe('2314');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([3, 2, 1, 4])), container);\n    expect(container.textContent).toBe('3214');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([3, 2, 4, 1])), container);\n    expect(container.textContent).toBe('3241');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  it('should move a element to the end', () => {\n    render(template(generateKeyNodes([1, 2, 3])), container);\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes([2, 3, 1])), container);\n    expect(container.textContent).toBe('231');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should move a element backwards', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([1, 4, 2, 3])), container);\n    expect(container.textContent).toBe('1423');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should swap first and last', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([4, 2, 3, 1])), container);\n    expect(container.textContent).toBe('4231');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  it('should move to left and replace', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([4, 1, 2, 3, 6])), container);\n    expect(container.textContent).toBe('41236');\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([4, 5, 2, 3, 0])), container);\n    expect(container.textContent).toBe('45230');\n    render(template(generateKeyNodes([1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(5);\n  });\n\n  it('should move to left and leave a hole', () => {\n    render(template(generateKeyNodes([1, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes([4, 6])), container);\n    expect(container.textContent).toBe('46');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should do something', () => {\n    render(template(generateKeyNodes([0, 1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(6);\n    render(template(generateKeyNodes([4, 3, 2, 1, 5, 0])), container);\n    expect(container.textContent).toBe('432150');\n    expect(container.firstChild.childNodes.length).toBe(6);\n  });\n\n  it('should cycle order correctly', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n    render(template(generateKeyNodes([2, 3, 4, 1])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('2341');\n    render(template(generateKeyNodes([3, 4, 1, 2])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('3412');\n    render(template(generateKeyNodes([4, 1, 2, 3])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('4123');\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n  });\n\n  it('should cycle order correctly in the other direction', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n    render(template(generateKeyNodes([4, 1, 2, 3])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('4123');\n    render(template(generateKeyNodes([3, 4, 1, 2])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('3412');\n    render(template(generateKeyNodes([2, 3, 4, 1])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('2341');\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n  });\n\n  it('should allow any character as a key', () => {\n    render(template(generateKeyNodes(['<WEIRD/&\\\\key>'])), container);\n    render(\n      template(\n        generateKeyNodes([\n          'INSANE/(/&\\\\key',\n          '<CRAZY/&\\\\key>',\n          '<WEIRD/&\\\\key>',\n        ]),\n      ),\n      container,\n    );\n    expect(container.textContent).toBe(\n      'INSANE/(/&\\\\key<CRAZY/&\\\\key><WEIRD/&\\\\key>',\n    );\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should reorder nodes', () => {\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n    render(\n      template(generateKeyNodes(['1', '2', '3', '4', 'abc', '6', 'def', '7'])),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n  });\n\n  it('should do a advanced shuffle - numbers and letters', () => {\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 1, 2, 3])),\n      container,\n    );\n    expect(container.textContent).toBe('abcd123');\n    expect(container.firstChild.childNodes.length).toBe(7);\n    render(\n      template(generateKeyNodes([1, 'e', 2, 'b', 'f', 'g', 'c', 'a', 3])),\n      container,\n    );\n    expect(container.textContent).toBe('1e2bfgca3');\n    expect(container.firstChild.childNodes.length).toBe(9);\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 1, 2, 3])),\n      container,\n    );\n    expect(container.textContent).toBe('abcd123');\n    expect(container.firstChild.childNodes.length).toBe(7);\n    render(\n      template(generateKeyNodes([0, 'e', 2, 'b', 'f', 'g', 'c', 'a', 4])),\n      container,\n    );\n    expect(container.textContent).toBe('0e2bfgca4');\n    expect(container.firstChild.childNodes.length).toBe(9);\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 1, 2, 3])),\n      container,\n    );\n    expect(container.textContent).toBe('abcd123');\n    expect(container.firstChild.childNodes.length).toBe(7);\n    render(\n      template(generateKeyNodes([1, 'e', 2, 'b', 'f', 'g', 'c', 'a', 3])),\n      container,\n    );\n    expect(container.textContent).toBe('1e2bfgca3');\n    expect(container.firstChild.childNodes.length).toBe(9);\n  });\n\n  it('should do a complex removal at the beginning', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes(['c', 'd'])), container);\n    expect(container.textContent).toBe('cd');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  it('should do move and sync nodes from right to left', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template(\n        generateKeyNodes(['c', 'l', 1, 2, 3, 4, 5, 6, 7, 8, 9, 'd', 'g', 'b']),\n      ),\n      container,\n    );\n    expect(container.textContent).toBe('cl123456789dgb');\n    expect(container.firstChild.childNodes.length).toBe(14);\n  });\n\n  describe('Should handle massive large arrays', () => {\n    let items;\n\n    beforeEach(function () {\n      items = new Array(1000);\n      for (let i = 0; i < 1000; i++) {\n        items[i] = i;\n      }\n    });\n\n    it('Should handle massive large arrays - initial', () => {\n      render(template(generateKeyNodes(items)), container);\n\n      expect(container.textContent).toEqual(items.join(''));\n    });\n\n    it('Should handle massive arrays shifting once by 2', () => {\n      items = items.concat(items.splice(0, 2));\n      render(template(generateKeyNodes(items)), container);\n\n      expect(container.textContent).toEqual(items.join(''));\n    });\n\n    for (let i = 0; i < 10; i++) {\n      it(\n        'Should handle massive arrays shifting ' + i + ' times by ' + i,\n        () => {\n          for (let j = 0; j < i; j++) {\n            items = items.concat(items.splice(i, j));\n          }\n          render(template(generateKeyNodes(items)), container);\n          expect(container.textContent).toEqual(items.join(''));\n        },\n      );\n    }\n  });\n\n  describe('Calendar like layout', () => {\n    interface AnimatedProps {\n      key: string;\n      children?: any;\n    }\n\n    class Animated extends Component<AnimatedProps, unknown> {\n      public componentDidAppear() {\n        // Trigger animation code paths on add\n      }\n\n      public componentWillDisappear(_dom, done) {\n        // Trigger animation code paths on remove\n        done();\n      }\n\n      public render({ children }: AnimatedProps) {\n        return <div>{children}</div>;\n      }\n    }\n\n    function o(text) {\n      return <Animated key={'o' + text}>{',o' + text}</Animated>;\n    }\n\n    function d(text) {\n      return <Animated key={'d' + text}>{',d' + text}</Animated>;\n    }\n\n    function wk(text) {\n      return <Animated key={'wk' + text}>{',wk' + text}</Animated>;\n    }\n\n    it('Should do complex suffle without duplications', () => {\n      const layout1 = [\n        wk(31),\n        d(1),\n        d(2),\n        d(3),\n        d(4),\n        d(5),\n        d(6),\n        d(7),\n        wk(32),\n        d(8),\n        d(9),\n        d(10),\n        d(11),\n        d(12),\n        d(13),\n        d(14),\n        wk(33),\n        d(15),\n        d(16),\n        d(17),\n        d(18),\n        d(19),\n        d(20),\n        d(21),\n        wk(34),\n        d(22),\n        d(23),\n        d(24),\n        d(25),\n        d(26),\n        d(27),\n        d(28),\n        wk(35),\n        d(29),\n        d(30),\n        d(31),\n        o(1),\n        o(2),\n        o(3),\n        o(4),\n        wk(36),\n        o(5),\n        o(6),\n        o(7),\n        o(8),\n        o(9),\n        o(10),\n        o(11),\n      ];\n      render(template(layout1), container);\n\n      expect(container.textContent).toBe(\n        ',wk31,d1,d2,d3,d4,d5,d6,d7,wk32,d8,d9,d10,d11,d12,d13,d14,wk33,d15,d16,d17,d18,d19,d20,d21,wk34,d22,d23,d24,d25,d26,d27,d28,wk35,d29,d30,d31,o1,o2,o3,o4,wk36,o5,o6,o7,o8,o9,o10,o11',\n      );\n\n      const layout2 = [\n        wk(35),\n        o(29),\n        o(30),\n        o(31),\n        d(1),\n        d(2),\n        d(3),\n        d(4),\n        wk(36),\n        d(5),\n        d(6),\n        d(7),\n        d(8),\n        d(9),\n        d(10),\n        d(11),\n        wk(37),\n        d(12),\n        d(13),\n        d(14),\n        d(15),\n        d(16),\n        d(17),\n        d(18),\n        wk(38),\n        d(19),\n        d(20),\n        d(21),\n        d(22),\n        d(23),\n        d(24),\n        d(25),\n        wk(39),\n        d(26),\n        d(27),\n        d(28),\n        d(29),\n        d(30),\n        o(1),\n        o(2),\n        wk(40),\n        o(3),\n        o(4),\n        o(5),\n        o(6),\n        o(7),\n        o(8),\n        o(9),\n      ];\n      render(template(layout2), container);\n\n      expect(container.textContent).toBe(\n        ',wk35,o29,o30,o31,d1,d2,d3,d4,wk36,d5,d6,d7,d8,d9,d10,d11,wk37,d12,d13,d14,d15,d16,d17,d18,wk38,d19,d20,d21,d22,d23,d24,d25,wk39,d26,d27,d28,d29,d30,o1,o2,wk40,o3,o4,o5,o6,o7,o8,o9',\n      );\n    });\n  });\n});\n\ninterface TagProps {\n  children: InfernoSingleNode;\n  id: string;\n}\n\nfunction factory(spyer?: jasmine.Spy) {\n  return {\n    Tag: ({ children }: TagProps) => {\n      return <div>{children}</div>;\n    },\n    onComponentDidAppear(_dom) {\n      spyer?.('didAppear');\n    },\n    onComponentWillDisappear(_dom, _props, callback) {\n      spyer?.('willDisappear');\n      callback();\n    },\n  };\n}\n\nfunction generateKeyNodes(array: Array<string | number>, spyer?) {\n  let i: number;\n  let id: string | number;\n  let key: string | number;\n  const children: InfernoNode[] = [];\n  let newKey: string | number | null;\n  const { Tag, onComponentDidAppear, onComponentWillDisappear } =\n    factory(spyer);\n\n  for (i = 0; i < array.length; i++) {\n    id = key = array[i];\n    if (key !== null && (typeof key !== 'string' || key[0] !== '#')) {\n      newKey = key;\n    } else {\n      newKey = null;\n    }\n\n    children.push(\n      <Tag\n        key={newKey}\n        id={String(id)}\n        onComponentDidAppear={onComponentDidAppear}\n        onComponentWillDisappear={onComponentWillDisappear}\n      >\n        {id}\n      </Tag>,\n    );\n  }\n  return children;\n}\n"
  },
  {
    "path": "packages/inferno/__tests__/async-setstate.spec.tsx",
    "content": "import { Component, render, rerender } from 'inferno';\n\ndescribe('Async set state issue', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should always call all set change callbacks', () => {\n    interface HoCProps {\n      run: number;\n    }\n\n    class HoC extends Component<HoCProps> {\n      constructor(props) {\n        super(props);\n\n        this.update = this.update.bind(this);\n      }\n\n      public update() {\n        this.setState({});\n      }\n\n      public render(props) {\n        return (\n          <div>\n            <Test update={this.update} run={props.run} name=\"first\" />\n            <Test update={this.update} run={props.run} name=\"second\" />\n          </div>\n        );\n      }\n    }\n\n    let _fromCWRPCBRequested = 0;\n    let _failureCreatorCBRequested = 0;\n    let _callMePlsCBRequested = 0;\n    let _justBecauseCBRequested = 0;\n    let _fromCWRPCalled = 0;\n    let _failureCreatorCalled = 0;\n    let _callMePlsCalled = 0;\n    let _justBecauseCalled = 0;\n\n    interface TestProps {\n      update: () => void;\n      run: number;\n      name: string;\n    }\n\n    interface TestState {\n      async: boolean;\n      counter: number;\n      failure: boolean;\n      success: number;\n    }\n\n    class Test extends Component<TestProps, TestState> {\n      public state: TestState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          async: false,\n          counter: 0,\n          failure: false,\n          success: 0,\n        };\n      }\n\n      public _forceASYNC() {\n        // hack just for testing, this forces parent is updating so we can test async setState flow\n        if (this.state.counter === 1) {\n          this.props.update();\n        }\n      }\n\n      public _justBecause() {\n        _justBecauseCalled++;\n        this._forceASYNC();\n\n        this.setState({\n          success: 2,\n        });\n      }\n\n      public _callMePls() {\n        _callMePlsCalled++;\n        this._forceASYNC();\n\n        _justBecauseCBRequested++;\n        this.setState(\n          {\n            success: 1,\n          },\n          this._justBecause,\n        );\n      }\n\n      public _failureCreator() {\n        _failureCreatorCalled++;\n        this._forceASYNC();\n\n        _callMePlsCBRequested++;\n        this.setState(\n          {\n            failure: true,\n          },\n          this._callMePls,\n        );\n      }\n\n      public _fromCWRP() {\n        _fromCWRPCalled++;\n        this._forceASYNC();\n\n        _failureCreatorCBRequested++;\n        // This setState triggers async flow\n        this.setState(\n          {\n            async: true,\n          },\n          this._failureCreator,\n        );\n      }\n\n      public componentWillReceiveProps(_nextProps, _nextContext) {\n        _fromCWRPCBRequested++;\n\n        this.setState(\n          {\n            counter: this.state.counter + 1,\n          },\n          this._fromCWRP,\n        );\n      }\n\n      public render() {\n        return (\n          <div>{`${this.props.name} ${this.state.success} ${this.state.counter} ${this.state.async} ${this.state.failure}`}</div>\n        );\n      }\n    }\n\n    render(<HoC run={1} />, container);\n    rerender();\n    render(<HoC run={2} />, container);\n    rerender();\n\n    // Set state should be called as many times as it was requested\n    expect(_fromCWRPCBRequested).toBe(_fromCWRPCalled);\n    expect(_callMePlsCBRequested).toBe(_callMePlsCalled);\n    expect(_failureCreatorCBRequested).toBe(_failureCreatorCalled);\n    expect(_justBecauseCBRequested).toBe(_justBecauseCalled);\n\n    // This assertion is just to document it used to be 4 iterations\n    expect(_fromCWRPCBRequested).toBe(4);\n    expect(_callMePlsCBRequested).toBe(4);\n    expect(_failureCreatorCBRequested).toBe(4);\n    expect(_justBecauseCBRequested).toBe(4);\n\n    expect(container.innerHTML).toBe(\n      '<div><div>first 2 2 true true</div><div>second 2 2 true true</div></div>',\n    );\n  });\n\n  it('Should always call all set change callbacks in order of setState requests', () => {\n    interface HoCProps {\n      run: number;\n    }\n\n    class HoC extends Component<HoCProps> {\n      constructor(props) {\n        super(props);\n\n        this.update = this.update.bind(this);\n      }\n\n      public update() {\n        this.setState({});\n      }\n\n      public render(props) {\n        return (\n          <div>\n            <TestBefore update={this.update} run={props.run} />\n            <TestAfter update={this.update} run={props.run} />\n          </div>\n        );\n      }\n    }\n\n    const orderOfCalls: string[] = [];\n    let testBeforeBeforeSpy: jasmine.Spy;\n    let testBeforeAfterSpy: jasmine.Spy;\n    let testAfterBeforeSpy: jasmine.Spy;\n    let testAfterAfterSpy: jasmine.Spy;\n\n    interface TestBeforeProps {\n      update: () => void;\n      run: number;\n    }\n    interface TestBeforeState {\n      async: number;\n      counter: number;\n    }\n\n    class TestBefore extends Component<TestBeforeProps, TestBeforeState> {\n      public state: TestBeforeState;\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          async: 0,\n          counter: 0,\n        };\n\n        testBeforeBeforeSpy = spyOn(this, '_before').and.callFake(function () {\n          orderOfCalls.push('testBeforeBefore');\n        });\n        testBeforeAfterSpy = spyOn(this, '_after').and.callFake(function () {\n          orderOfCalls.push('testBeforeAfter');\n        });\n      }\n\n      public _forceASYNC() {\n        // hack just for testing, this forces parent is updating so we can test async setState flow\n        if (this.state.counter === 1) {\n          this.props.update();\n        }\n      }\n\n      public _before() {}\n\n      public _after() {}\n\n      public _fromCWRP() {\n        this._forceASYNC();\n\n        this.setState(\n          {\n            async: 1,\n          },\n          this._before,\n        );\n\n        this.setState(\n          {\n            async: 2,\n          },\n          this._after,\n        );\n      }\n\n      public componentWillReceiveProps(_nextProps, _nextContext) {\n        this.setState(\n          {\n            counter: this.state.counter + 1,\n          },\n          this._fromCWRP,\n        );\n      }\n\n      public render() {\n        return <div>{`${this.state.async}`}</div>;\n      }\n    }\n\n    interface TestAfterProps {\n      update: () => void;\n      run: number;\n    }\n\n    interface TestAfterState {\n      async: number;\n      counter: number;\n    }\n\n    class TestAfter extends Component<TestAfterProps, TestAfterState> {\n      public state: TestAfterState;\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          async: 0,\n          counter: 0,\n        };\n\n        testAfterBeforeSpy = spyOn(this, '_before').and.callFake(function () {\n          orderOfCalls.push('testAfterBefore');\n        });\n        testAfterAfterSpy = spyOn(this, '_after').and.callFake(function () {\n          orderOfCalls.push('testAfterAfter');\n        });\n      }\n\n      public _forceASYNC() {\n        // hack just for testing, this forces parent is updating so we can test async setState flow\n        if (this.state.counter === 1) {\n          this.props.update();\n        }\n      }\n\n      public _before() {}\n\n      public _after() {}\n\n      public _fromCWRP() {\n        this._forceASYNC();\n\n        this.setState(\n          {\n            async: 1,\n          },\n          this._before,\n        );\n\n        this.setState(\n          {\n            async: 2,\n          },\n          this._after,\n        );\n      }\n\n      public componentWillReceiveProps(_nextProps, _nextContext) {\n        this.setState(\n          {\n            counter: this.state.counter + 1,\n          },\n          this._fromCWRP,\n        );\n      }\n\n      public render() {\n        return <div>{`${this.state.async}`}</div>;\n      }\n    }\n\n    render(<HoC run={1} />, container);\n    rerender();\n\n    render(<HoC run={2} />, container);\n    rerender();\n\n    // Set state should be called as many times as it was requested\n    expect(testBeforeBeforeSpy!).toHaveBeenCalledTimes(2);\n    expect(testBeforeAfterSpy!).toHaveBeenCalledTimes(2);\n    expect(testAfterBeforeSpy!).toHaveBeenCalledTimes(2);\n    expect(testAfterAfterSpy!).toHaveBeenCalledTimes(2);\n\n    expect(orderOfCalls).toEqual([\n      'testBeforeBefore',\n      'testBeforeAfter',\n      'testBeforeBefore',\n      'testBeforeAfter',\n      'testAfterBefore',\n      'testAfterAfter',\n      'testAfterBefore',\n      'testAfterAfter',\n    ]);\n\n    expect(container.innerHTML).toBe('<div><div>2</div><div>2</div></div>');\n  });\n\n  it('Should not call applystate for components which were unmounted during the micro task startup', function () {\n    interface HoCProps {\n      run: number;\n    }\n\n    class HoC extends Component<HoCProps> {\n      constructor(props) {\n        super(props);\n\n        this.update = this.update.bind(this);\n      }\n\n      public update() {\n        this.setState({});\n      }\n\n      public render(props) {\n        return (\n          <div>\n            <TestBefore update={this.update} run={props.run} />\n            <TestAfter update={this.update} run={props.run} />\n          </div>\n        );\n      }\n    }\n\n    let testBeforeBeforeSpy: jasmine.Spy;\n    let testBeforeAfterSpy: jasmine.Spy;\n    let testAfterBeforeSpy: jasmine.Spy;\n    let testAfterAfterSpy: jasmine.Spy;\n\n    interface TestBeforeProps {\n      update: () => void;\n      run: number;\n    }\n    interface TestBeforeState {\n      async: number;\n      counter: number;\n    }\n\n    class TestBefore extends Component<TestBeforeProps, TestBeforeState> {\n      public state: TestBeforeState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          async: 0,\n          counter: 0,\n        };\n\n        testBeforeBeforeSpy = spyOn(this, '_before');\n        testBeforeAfterSpy = spyOn(this, '_after');\n      }\n\n      public _forceASYNC() {\n        // hack just for testing, this forces parent is updating so we can test async setState flow\n        if (this.state.counter === 1) {\n          this.props.update();\n        }\n      }\n\n      public _before() {}\n\n      public _after() {}\n\n      public _fromCWRP() {\n        this._forceASYNC();\n\n        this.setState(\n          {\n            async: 1,\n          },\n          this._before,\n        );\n\n        this.setState(\n          {\n            async: 2,\n          },\n          this._after,\n        );\n      }\n\n      public componentWillReceiveProps(_nextProps, _nextContext) {\n        this.setState(\n          {\n            counter: this.state.counter + 1,\n          },\n          this._fromCWRP,\n        );\n      }\n\n      public render() {\n        return <div>{`${this.state.async}`}</div>;\n      }\n    }\n\n    interface TestAfterProps {\n      update: () => void;\n      run: number;\n    }\n\n    interface TestAfterState {\n      async: number;\n      counter: number;\n    }\n\n    class TestAfter extends Component<TestAfterProps, TestAfterState> {\n      public state: TestAfterState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          async: 0,\n          counter: 0,\n        };\n\n        testAfterBeforeSpy = spyOn(this, '_before');\n        testAfterAfterSpy = spyOn(this, '_after');\n      }\n\n      public _forceASYNC() {\n        // hack just for testing, this forces parent is updating so we can test async setState flow\n        if (this.state.counter === 1) {\n          this.props.update();\n        }\n      }\n\n      public _before() {}\n\n      public _after() {}\n\n      public _fromCWRP() {\n        this._forceASYNC();\n\n        this.setState(\n          {\n            async: 1,\n          },\n          this._before,\n        );\n\n        this.setState(\n          {\n            async: 2,\n          },\n          this._after,\n        );\n      }\n\n      public componentWillReceiveProps(_nextProps, _nextContext) {\n        this.setState(\n          {\n            counter: this.state.counter + 1,\n          },\n          this._fromCWRP,\n        );\n      }\n\n      public render() {\n        return <div>{`${this.state.async}`}</div>;\n      }\n    }\n\n    render(<HoC run={1} />, container);\n    rerender();\n    render(<HoC run={2} />, container);\n    rerender();\n    render(null, container);\n    rerender();\n\n    // Set state should be called as many times as it was requested\n    expect(testBeforeBeforeSpy!.calls.count()).toBe(2);\n    expect(testBeforeAfterSpy!.calls.count()).toBe(2);\n    expect(testAfterBeforeSpy!.calls.count()).toBe(2);\n    expect(testAfterAfterSpy!.calls.count()).toBe(2);\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/blueprints.spec.tsx",
    "content": "import { Component, render } from 'inferno';\n\ndescribe('Blueprints (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    document.body.removeChild(container);\n    container = null;\n  });\n\n  describe('Should have parentDOM defined #1', () => {\n    class A extends Component {\n      public render() {\n        return <div>A</div>;\n      }\n    }\n\n    class B extends Component {\n      public render() {\n        return <span>B</span>;\n      }\n    }\n\n    interface CounterProps {\n      car: string;\n    }\n\n    interface CounterState {\n      bool: boolean;\n    }\n\n    class Counter extends Component<CounterProps, CounterState> {\n      public state: CounterState;\n\n      constructor(props) {\n        super(props);\n        this.state = {\n          bool: false,\n        };\n        this.btnCount = this.btnCount.bind(this);\n      }\n\n      public btnCount() {\n        this.setState({\n          bool: !this.state.bool,\n        });\n      }\n\n      public render({ car }) {\n        return (\n          <div className=\"my-component\">\n            <h1>\n              {car} {this.state.bool ? <A /> : <B />}\n            </h1>\n            <button type=\"button\" onClick={this.btnCount}>\n              btn\n            </button>\n          </div>\n        );\n      }\n    }\n\n    class Wrapper extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      public render() {\n        return (\n          <div>\n            {['Saab', 'Volvo', 'BMW'].map(function (c) {\n              return <Counter car={c} />;\n            })}\n          </div>\n        );\n      }\n    }\n\n    it('Initial render (creation)', () => {\n      render(<Wrapper />, container);\n\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"my-component\"><h1>Saab <span>B</span></h1><button type=\"button\">btn</button></div><div class=\"my-component\"><h1>Volvo <span>B</span></h1><button type=\"button\">btn</button></div><div class=\"my-component\"><h1>BMW <span>B</span></h1><button type=\"button\">btn</button></div></div>',\n      );\n\n      render(null, container);\n    });\n\n    it('Second render (update)', () => {\n      render(<Wrapper />, container);\n      const buttons = container.querySelectorAll('button');\n      for (const button of buttons) {\n        button.click();\n      }\n\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"my-component\"><h1>Saab <div>A</div></h1><button type=\"button\">btn</button></div><div class=\"my-component\"><h1>Volvo <div>A</div></h1><button type=\"button\">btn</button></div><div class=\"my-component\"><h1>BMW <div>A</div></h1><button type=\"button\">btn</button></div></div>',\n      );\n      render(null, container);\n    });\n  });\n\n  describe('Infinite loop issue', () => {\n    it('Should not get stuck when doing setState from ref callback', (done) => {\n      interface AProps {\n        open?: boolean;\n      }\n\n      interface AState {\n        text: string;\n      }\n\n      class A extends Component<AProps, AState> {\n        public state: Readonly<AState>;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            text: 'foo',\n          };\n\n          this.onWilAttach = this.onWilAttach.bind(this);\n        }\n\n        public onWilAttach() {\n          this.setState({\n            text: 'animate',\n          });\n        }\n\n        public render() {\n          if (!this.props.open) {\n            return null;\n          }\n\n          return <div ref={this.onWilAttach}>{this.state.text}</div>;\n        }\n      }\n\n      render(<A />, container);\n\n      render(<A open={true} />, container);\n      setTimeout(() => {\n        expect(container.innerHTML).toBe('<div>animate</div>');\n        done();\n      }, 10);\n    });\n  });\n\n  describe('Refs inside components', () => {\n    it('Should have refs defined when componentDidMount is called', () => {\n      class Com extends Component {\n        private _first: HTMLDivElement | null;\n        private _second: HTMLSpanElement | null;\n\n        constructor(props) {\n          super(props);\n          this._first = null;\n          this._second = null;\n        }\n\n        public componentDidMount() {\n          expect(this._first).not.toBe(null);\n          expect(this._second).not.toBe(null);\n        }\n\n        public render() {\n          return (\n            <div ref={(node) => (this._first = node)}>\n              <span>1</span>\n              <span ref={(node) => (this._second = node)}>2</span>\n            </div>\n          );\n        }\n      }\n\n      render(<Com />, container);\n    });\n  });\n\n  describe('Spread operator and templates', () => {\n    it('Should be able to update property', () => {\n      interface AProps {\n        disabled?: boolean;\n        args?: object;\n      }\n      class A extends Component<AProps> {\n        constructor(props) {\n          super(props);\n        }\n\n        public render() {\n          return (\n            <div>\n              <input disabled={this.props.disabled} {...this.props.args} />\n            </div>\n          );\n        }\n      }\n\n      render(<A disabled={true} />, container);\n      let input = container.querySelector('input');\n      expect(input.disabled).toBe(true);\n\n      render(<A disabled={false} />, container);\n      input = container.querySelector('input');\n      expect(input.disabled).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/children.spec.tsx",
    "content": "import { Component, type InfernoNode, type Key, render } from 'inferno';\n\ndescribe('Children - (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('keyed - children', function () {\n    it('Should push to correct location when it keyed list has siblings', function () {\n      const _tabs = [{ title: 'Item A' }, { title: 'Item B' }];\n      interface TabProps {\n        title?: string;\n        onSelect?: () => void;\n        key?: Key;\n        id?: string;\n      }\n\n      function Tab({ title, onSelect, key, id }: TabProps) {\n        return (\n          <div id={id} key={key} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.push({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab, i) => (\n              <Tab\n                key={'Item ' + i}\n                title={tab.title}\n                onSelect={() => undefined}\n              />\n            ))}\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div id=\"add\">Add</div></div>',\n      );\n      let addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div>New 2</div><div id=\"add\">Add</div></div>',\n      );\n      addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div>New 2</div><div>New 3</div><div id=\"add\">Add</div></div>',\n      );\n      addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div>New 2</div><div>New 3</div><div>New 4</div><div id=\"add\">Add</div></div>',\n      );\n      addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div>New 2</div><div>New 3</div><div>New 4</div><div>New 5</div><div id=\"add\">Add</div></div>',\n      );\n    });\n\n    it('Should append child node to correct location when its empty at the beginning ', function () {\n      const _tabs: Array<{ title: string }> = [];\n      interface TabProps {\n        title?: string;\n        onSelect?: () => void;\n        key?: Key;\n        id?: string;\n      }\n\n      function Tab({ title, onSelect, key, id }: TabProps) {\n        return (\n          <div id={id} key={key} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.push({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab, i) => (\n              <Tab\n                key={'Item ' + i}\n                title={tab.title}\n                onSelect={() => undefined}\n              />\n            ))}\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div id=\"add\">Add</div></div>',\n      );\n      let addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 0</div><div id=\"add\">Add</div></div>',\n      );\n      addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 0</div><div>New 1</div><div id=\"add\">Add</div></div>',\n      );\n    });\n\n    it('Should append child node to correct location when its empty at the beginning ', function () {\n      const _tabs: Array<{ title: string }> = [];\n\n      interface TabProps {\n        title?: string;\n        onSelect?: () => void;\n        key?: Key;\n        id?: string;\n      }\n\n      function Tab({ title, onSelect, key, id }: TabProps) {\n        return (\n          <div id={id} key={key} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.push({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n            {tabs.map((tab, i) => (\n              <Tab\n                key={'Item ' + i}\n                title={tab.title}\n                onSelect={() => undefined}\n              />\n            ))}\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div id=\"add\">Add</div></div>',\n      );\n      let addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div id=\"add\">Add</div><div>New 0</div></div>',\n      );\n      addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div id=\"add\">Add</div><div>New 0</div><div>New 1</div></div>',\n      );\n    });\n\n    it('Should append child node to correct location when its empty at the beginning ', function () {\n      const _tabs: Array<{ title: string }> = [];\n      interface TabProps {\n        title?: string;\n        onSelect?: () => void;\n        key?: Key;\n        id?: string;\n      }\n\n      function Tab({ title, onSelect, key, id }: TabProps) {\n        return (\n          <div id={id} key={key} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.push({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab, i) => (\n              <Tab\n                key={'Item ' + i}\n                title={tab.title}\n                onSelect={() => undefined}\n              />\n            ))}\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n            {tabs.map((tab, i) => (\n              <Tab\n                key={'Item ' + i}\n                title={tab.title}\n                onSelect={() => undefined}\n              />\n            ))}\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div id=\"add\">Add</div></div>',\n      );\n      let addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 0</div><div id=\"add\">Add</div><div>New 0</div></div>',\n      );\n      addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 0</div><div>New 1</div><div id=\"add\">Add</div><div>New 0</div><div>New 1</div></div>',\n      );\n    });\n\n    it('Should appendx3 to correct location when it keyed list has siblings', function () {\n      const _tabs = [{ title: 'Item A' }, { title: 'Item B' }];\n      interface TabProps {\n        title?: string;\n        onSelect?: () => void;\n        key?: Key;\n        id?: string;\n      }\n\n      function Tab({ title, onSelect, key, id }: TabProps) {\n        return (\n          <div id={id} key={key} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.push({ title: 'New ' + tabs.length });\n          tabs.push({ title: 'New ' + tabs.length });\n          tabs.push({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab, i) => (\n              <Tab\n                key={'Item ' + i}\n                title={tab.title}\n                onSelect={() => undefined}\n              />\n            ))}\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div id=\"add\">Add</div></div>',\n      );\n      const addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div>New 2</div><div>New 3</div><div>New 4</div><div id=\"add\">Add</div></div>',\n      );\n    });\n\n    it('Should unshiftx3 to correct location when it keyed list has siblings', function () {\n      const _tabs = [{ title: 'Item A' }, { title: 'Item B' }];\n      interface TabProps {\n        title?: string;\n        onSelect?: () => void;\n        key?: Key;\n        id?: string;\n      }\n\n      function Tab({ title, onSelect, key, id }: TabProps) {\n        return (\n          <div id={id} key={key} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.unshift({ title: 'New ' + tabs.length });\n          tabs.unshift({ title: 'New ' + tabs.length });\n          tabs.unshift({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab, i) => (\n              <Tab\n                key={'Item ' + i}\n                title={tab.title}\n                onSelect={() => undefined}\n              />\n            ))}\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div id=\"add\">Add</div></div>',\n      );\n      const addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 4</div><div>New 3</div><div>New 2</div><div>Item A</div><div>Item B</div><div id=\"add\">Add</div></div>',\n      );\n    });\n\n    it('Inline text element before array list', function () {\n      const _tabs: Array<{ title: string }> = [];\n\n      interface TabProps {\n        title?: string;\n        key?: Key;\n      }\n\n      function Tab({ title, key }: TabProps) {\n        return <div key={key}>{title}</div>;\n      }\n\n      function TabGroup({ tabs }) {\n        return (\n          <div className=\"tab-group\">\n            inlineText\n            {tabs.map((tab, i) => (\n              <Tab key={'Item ' + i} title={tab.title} />\n            ))}\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\">inlineText</div>',\n      );\n\n      _tabs.push({ title: 'New ' + _tabs.length });\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\">inlineText<div>New 0</div></div>',\n      );\n    });\n\n    it('Inline text element after array list', function () {\n      const _tabs: Array<{ title: string }> = [];\n      interface TabProps {\n        title?: string;\n        key?: Key;\n      }\n\n      function Tab({ title, key }: TabProps) {\n        return <div key={key}>{title}</div>;\n      }\n\n      function TabGroup({ tabs }) {\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab, i) => (\n              <Tab key={'Item ' + i} title={tab.title} />\n            ))}\n            inlineText\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\">inlineText</div>',\n      );\n\n      _tabs.push({ title: 'New ' + _tabs.length });\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 0</div>inlineText</div>',\n      );\n    });\n  });\n\n  describe('nonKeyed - children', function () {\n    it('Should push to correct location when it keyed list has siblings', function () {\n      const _tabs = [{ title: 'Item A' }, { title: 'Item B' }];\n\n      interface TabProps {\n        title?: string;\n        id?: string;\n        onSelect?: () => void;\n      }\n\n      function Tab({ title, id, onSelect }: TabProps) {\n        return (\n          <div id={id} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.push({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab) => (\n              <Tab title={tab.title} onSelect={() => undefined} />\n            ))}\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div id=\"add\">Add</div></div>',\n      );\n      let addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div>New 2</div><div id=\"add\">Add</div></div>',\n      );\n      addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div>New 2</div><div>New 3</div><div id=\"add\">Add</div></div>',\n      );\n      addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div>New 2</div><div>New 3</div><div>New 4</div><div id=\"add\">Add</div></div>',\n      );\n      addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div>New 2</div><div>New 3</div><div>New 4</div><div>New 5</div><div id=\"add\">Add</div></div>',\n      );\n    });\n\n    it('Should append child node to correct location when its empty at the beginning ', function () {\n      const _tabs: Array<{ title: string }> = [];\n\n      interface TabProps {\n        title?: string;\n        id?: string;\n        onSelect?: () => void;\n      }\n\n      function Tab({ title, id, onSelect }: TabProps) {\n        return (\n          <div id={id} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.push({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab) => (\n              <Tab title={tab.title} onSelect={() => undefined} />\n            ))}\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div id=\"add\">Add</div></div>',\n      );\n      let addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 0</div><div id=\"add\">Add</div></div>',\n      );\n      addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 0</div><div>New 1</div><div id=\"add\">Add</div></div>',\n      );\n    });\n\n    it('Should append child node to correct location when its empty at the beginning ', function () {\n      const _tabs: Array<{ title: string }> = [];\n\n      interface TabProps {\n        title?: string;\n        id?: string;\n        onSelect?: () => void;\n      }\n\n      function Tab({ title, id, onSelect }: TabProps) {\n        return (\n          <div id={id} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.push({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n            {tabs.map((tab) => (\n              <Tab title={tab.title} onSelect={() => undefined} />\n            ))}\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div id=\"add\">Add</div></div>',\n      );\n      const addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div id=\"add\">Add</div><div>New 0</div></div>',\n      );\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div id=\"add\">Add</div><div>New 0</div><div>New 1</div></div>',\n      );\n    });\n\n    it('Should append child node to correct location when its empty at the beginning ', function () {\n      const _tabs: Array<{ title: string }> = [];\n\n      interface TabProps {\n        title?: string;\n        id?: string;\n        onSelect?: () => void;\n      }\n\n      function Tab({ title, id, onSelect }: TabProps) {\n        return (\n          <div id={id} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.push({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab) => (\n              <Tab title={tab.title} onSelect={() => undefined} />\n            ))}\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n            {tabs.map((tab) => (\n              <Tab title={tab.title} onSelect={() => undefined} />\n            ))}\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div id=\"add\">Add</div></div>',\n      );\n      let addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 0</div><div id=\"add\">Add</div><div>New 0</div></div>',\n      );\n      addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 0</div><div>New 1</div><div id=\"add\">Add</div><div>New 0</div><div>New 1</div></div>',\n      );\n    });\n\n    it('Should appendx3 to correct location when it list has siblings', function () {\n      const _tabs = [{ title: 'Item A' }, { title: 'Item B' }];\n\n      interface TabProps {\n        title?: string;\n        id?: string;\n        onSelect?: () => void;\n      }\n\n      function Tab({ title, id, onSelect }: TabProps) {\n        return (\n          <div id={id} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.push({ title: 'New ' + tabs.length });\n          tabs.push({ title: 'New ' + tabs.length });\n          tabs.push({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab) => (\n              <Tab title={tab.title} onSelect={() => undefined} />\n            ))}\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div id=\"add\">Add</div></div>',\n      );\n      const addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div>New 2</div><div>New 3</div><div>New 4</div><div id=\"add\">Add</div></div>',\n      );\n    });\n\n    it('Should unshiftx3 to correct location when it list has siblings', function () {\n      const _tabs = [{ title: 'Item A' }, { title: 'Item B' }];\n\n      interface TabProps {\n        title?: string;\n        id?: string;\n        onSelect?: () => void;\n      }\n\n      function Tab({ title, id, onSelect }: TabProps) {\n        return (\n          <div id={id} onClick={onSelect}>\n            {title}\n          </div>\n        );\n      }\n\n      function TabGroup({ tabs }) {\n        function create() {\n          tabs.unshift({ title: 'New ' + tabs.length });\n          tabs.unshift({ title: 'New ' + tabs.length });\n          tabs.unshift({ title: 'New ' + tabs.length });\n          renderIt();\n        }\n\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab) => (\n              <Tab title={tab.title} onSelect={() => undefined} />\n            ))}\n            <Tab onSelect={create} id=\"add\" title=\"Add\" />\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>Item A</div><div>Item B</div><div id=\"add\">Add</div></div>',\n      );\n      const addTab = container.querySelector('#add');\n      addTab.click();\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 4</div><div>New 3</div><div>New 2</div><div>Item A</div><div>Item B</div><div id=\"add\">Add</div></div>',\n      );\n    });\n\n    it('Inline text element before array list', function () {\n      const _tabs: Array<{ title: string }> = [];\n\n      function Tab({ title }) {\n        return <div>{title}</div>;\n      }\n\n      function TabGroup({ tabs }) {\n        return (\n          <div className=\"tab-group\">\n            inlineText\n            {tabs.map((tab) => (\n              <Tab title={tab.title} />\n            ))}\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\">inlineText</div>',\n      );\n\n      _tabs.push({ title: 'New ' + _tabs.length });\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\">inlineText<div>New 0</div></div>',\n      );\n    });\n\n    it('Inline text element after array list', function () {\n      const _tabs: Array<{ title: string }> = [];\n\n      function Tab({ title }) {\n        return <div>{title}</div>;\n      }\n\n      function TabGroup({ tabs }) {\n        return (\n          <div className=\"tab-group\">\n            {tabs.map((tab) => (\n              <Tab title={tab.title} />\n            ))}\n            inlineText\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(<TabGroup tabs={_tabs} />, container);\n      }\n\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\">inlineText</div>',\n      );\n\n      _tabs.push({ title: 'New ' + _tabs.length });\n      renderIt();\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"tab-group\"><div>New 0</div>inlineText</div>',\n      );\n    });\n  });\n\n  describe('mixed children edge cases', function () {\n    it('NONKEYED - should remove children from correct location when there is dynamic static item', function () {\n      const items = ['a', 'b', 'c'];\n      const emptyArray = [];\n      const items3 = ['v', 'a'];\n      let visible = false;\n      let activeOne;\n\n      function Loop({ text }) {\n        return <p>{text}</p>;\n      }\n\n      function Looper({ collectionOne, visibleStatic }) {\n        return (\n          <div className=\"c\">\n            {visibleStatic ? <Loop text=\"static\" /> : null}\n            {collectionOne.map((text) => (\n              <Loop text={text} />\n            ))}\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(\n          <Looper collectionOne={activeOne} visibleStatic={visible} />,\n          container,\n        );\n      }\n\n      visible = true;\n      activeOne = items;\n      renderIt();\n      expect(container.innerHTML).toBe(\n        '<div class=\"c\"><p>static</p><p>a</p><p>b</p><p>c</p></div>',\n      );\n\n      visible = false;\n      activeOne = items3;\n      renderIt();\n      expect(container.innerHTML).toBe('<div class=\"c\"><p>v</p><p>a</p></div>');\n\n      visible = true;\n      activeOne = items3;\n      renderIt();\n      expect(container.innerHTML).toBe(\n        '<div class=\"c\"><p>static</p><p>v</p><p>a</p></div>',\n      );\n\n      visible = true;\n      activeOne = emptyArray;\n      renderIt();\n      expect(container.innerHTML).toBe('<div class=\"c\"><p>static</p></div>');\n    });\n\n    it('NONKEYED - should remove children from correct location when there is 2 dynamic static items and 2 lists', function () {\n      const items = ['a', 'b', 'c'];\n      const emptyArray = [];\n      const items3 = ['v', 'a'];\n\n      let activeOne;\n      let activeTwo;\n      let visibleOne = false;\n      let visibleTwo = false;\n\n      function Loop({ text }) {\n        return <p>{text}</p>;\n      }\n\n      function Looper({\n        collectionOne,\n        visibleStaticOne,\n        collectionTwo,\n        visibleStaticTwo,\n      }) {\n        return (\n          <div className=\"c\">\n            {visibleStaticOne ? <Loop text=\"static\" /> : null}\n            {collectionOne.map((text) => (\n              <Loop text={text} />\n            ))}\n            {visibleStaticTwo ? <Loop text=\"static\" /> : null}\n            {collectionTwo.map((text) => (\n              <Loop text={text} />\n            ))}\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(\n          <Looper\n            collectionOne={activeOne}\n            visibleStaticOne={visibleOne}\n            collectionTwo={activeTwo}\n            visibleStaticTwo={visibleTwo}\n          />,\n          container,\n        );\n      }\n\n      visibleOne = true;\n      activeOne = items;\n      visibleTwo = false;\n      activeTwo = emptyArray;\n      renderIt();\n      expect(container.innerHTML).toBe(\n        '<div class=\"c\"><p>static</p><p>a</p><p>b</p><p>c</p></div>',\n      );\n\n      visibleOne = true;\n      activeOne = emptyArray;\n      visibleTwo = true;\n      activeTwo = items;\n      renderIt();\n      expect(container.innerHTML).toBe(\n        '<div class=\"c\"><p>static</p><p>static</p><p>a</p><p>b</p><p>c</p></div>',\n      );\n\n      visibleOne = false;\n      activeOne = items3;\n      visibleTwo = false;\n      activeTwo = emptyArray;\n      renderIt();\n      expect(container.innerHTML).toBe('<div class=\"c\"><p>v</p><p>a</p></div>');\n\n      visibleOne = true;\n      activeOne = items;\n      visibleTwo = true;\n      activeTwo = emptyArray;\n      renderIt();\n      expect(container.innerHTML).toBe(\n        '<div class=\"c\"><p>static</p><p>a</p><p>b</p><p>c</p><p>static</p></div>',\n      );\n    });\n\n    it('KEYED - should remove children from correct location when there is dynamic static item', function () {\n      const items = ['a', 'b', 'c'];\n      const emptyArray = [];\n      const items3 = ['v', 'a'];\n      let visible = false;\n\n      let activeOne;\n\n      function Loop({ text }) {\n        return <p>{text}</p>;\n      }\n\n      function Looper({ collectionOne, visibleStatic }) {\n        return (\n          <div className=\"c\">\n            {visibleStatic ? <Loop text=\"static\" /> : null}\n            {collectionOne.map((text, i) => (\n              <Loop key={i} text={text} />\n            ))}\n          </div>\n        );\n      }\n\n      function renderIt() {\n        render(\n          <Looper collectionOne={activeOne} visibleStatic={visible} />,\n          container,\n        );\n      }\n\n      visible = true;\n      activeOne = items;\n      renderIt();\n      expect(container.innerHTML).toBe(\n        '<div class=\"c\"><p>static</p><p>a</p><p>b</p><p>c</p></div>',\n      );\n\n      visible = false;\n      activeOne = items3;\n      renderIt();\n      expect(container.innerHTML).toBe('<div class=\"c\"><p>v</p><p>a</p></div>');\n\n      visible = true;\n      activeOne = items3;\n      renderIt();\n      expect(container.innerHTML).toBe(\n        '<div class=\"c\"><p>static</p><p>v</p><p>a</p></div>',\n      );\n\n      visible = true;\n      activeOne = emptyArray;\n      renderIt();\n      expect(container.innerHTML).toBe('<div class=\"c\"><p>static</p></div>');\n    });\n  });\n\n  describe('Functions non keyed', () => {\n    it('Should render correctly functions and nodes mixed', () => {\n      let updaterFirst: (() => void) | null = null;\n      let updaterSecond: (() => void) | null = null;\n\n      interface AState {\n        first: boolean;\n        second: boolean;\n      }\n\n      class A extends Component<unknown, AState> {\n        public state: Readonly<AState>;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            first: true,\n            second: true,\n          };\n\n          updaterFirst = () => {\n            this.setState({ first: !this.state.first });\n          };\n          updaterSecond = () => {\n            this.setState({ second: !this.state.second });\n          };\n        }\n\n        public render() {\n          return (\n            <div>\n              <p>1</p>\n              {function () {\n                if (this.state.first) {\n                  return <span>abc</span>;\n                }\n                return null;\n              }.call(this)}\n              <p>2</p>\n              {function () {\n                if (this.state.second) {\n                  return <span>def</span>;\n                }\n                return null;\n              }.call(this)}\n              <p>3</p>\n            </div>\n          );\n        }\n      }\n\n      render(<A />, container);\n      expect(container.innerHTML).toBe(\n        '<div><p>1</p><span>abc</span><p>2</p><span>def</span><p>3</p></div>',\n      );\n      updaterFirst!();\n      expect(container.innerHTML).toBe(\n        '<div><p>1</p><p>2</p><span>def</span><p>3</p></div>',\n      );\n      updaterSecond!();\n      expect(container.innerHTML).toBe('<div><p>1</p><p>2</p><p>3</p></div>');\n      updaterSecond!();\n      expect(container.innerHTML).toBe(\n        '<div><p>1</p><p>2</p><span>def</span><p>3</p></div>',\n      );\n      updaterFirst!();\n      expect(container.innerHTML).toBe(\n        '<div><p>1</p><span>abc</span><p>2</p><span>def</span><p>3</p></div>',\n      );\n    });\n  });\n\n  describe('JSX plugin', () => {\n    it('Should not have undefined properties', () => {\n      class A extends Component {\n        constructor(props) {\n          super(props);\n        }\n\n        public render() {\n          return <div>{this.props.children}</div>;\n        }\n      }\n\n      class B extends Component {\n        constructor(props) {\n          super(props);\n        }\n\n        public callback() {}\n\n        public render() {\n          return (\n            <A>\n              <div onclick={this.callback}>B</div>\n            </A>\n          );\n        }\n      }\n\n      render(<B />, container);\n    });\n  });\n\n  describe('Rendering null on child node', () => {\n    it('Should trigger unmount', () => {\n      interface AProps {\n        test: InfernoNode;\n      }\n      class A extends Component<AProps> {\n        constructor(props) {\n          super(props);\n        }\n\n        public render() {\n          return <div>{this.props.test}</div>;\n        }\n      }\n\n      class B extends Component {\n        constructor(props) {\n          super(props);\n        }\n\n        public componentWillUnmount() {}\n\n        public render() {\n          return <p>B</p>;\n        }\n      }\n\n      const unmountSpy = spyOn(B.prototype, 'componentWillUnmount');\n      render(<A test={<B />} />, container);\n      expect(container.innerHTML).toBe('<div><p>B</p></div>');\n      render(<A test={null} />, container);\n      expect(container.innerHTML).toBe('<div></div>');\n      expect(unmountSpy.calls.count()).toBe(1);\n    });\n  });\n\n  describe('VFragment within other nodes', () => {\n    it('Should not clear nodes when non keyed', () => {\n      const Nodes = ({ items }) => (\n        <div>\n          <div>test</div>\n          {items.map((item) => (\n            <span>{item}</span>\n          ))}\n          <div>end</div>\n        </div>\n      );\n\n      render(<Nodes items={[1, 2, 3]} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>test</div><span>1</span><span>2</span><span>3</span><div>end</div></div>',\n      );\n\n      render(<Nodes items={[3, 2, 1]} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>test</div><span>3</span><span>2</span><span>1</span><div>end</div></div>',\n      );\n\n      render(<Nodes items={[9, 8, 7]} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>test</div><span>9</span><span>8</span><span>7</span><div>end</div></div>',\n      );\n\n      render(<Nodes items={[]} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>test</div><div>end</div></div>',\n      );\n    });\n\n    it('Should not clear nodes when keyed inside vFragment', () => {\n      const Nodes = ({ items }) => (\n        <div>\n          <div>test</div>\n          {items.map((item) => (\n            <span key={item}>{item}</span>\n          ))}\n          <div>end</div>\n        </div>\n      );\n\n      render(<Nodes items={[1, 2, 3]} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>test</div><span>1</span><span>2</span><span>3</span><div>end</div></div>',\n      );\n\n      render(<Nodes items={[3, 2, 1]} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>test</div><span>3</span><span>2</span><span>1</span><div>end</div></div>',\n      );\n\n      render(<Nodes items={[9, 8, 7]} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>test</div><span>9</span><span>8</span><span>7</span><div>end</div></div>',\n      );\n\n      render(<Nodes items={[]} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>test</div><div>end</div></div>',\n      );\n    });\n\n    it('Should not clear nodes when keyed inside vFragment #2', () => {\n      const Nodes = ({ items }) => (\n        <div>\n          <div>test</div>\n          {items.map((item) => (\n            <span key={item}>{item}</span>\n          ))}\n          <div>end</div>\n        </div>\n      );\n\n      render(<Nodes items={[1]} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>test</div><span>1</span><div>end</div></div>',\n      );\n\n      render(<Nodes items={[]} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>test</div><div>end</div></div>',\n      );\n\n      render(null, container);\n      expect(container.innerHTML).toBe('');\n\n      render(<Nodes items={[1, 2, 3]} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>test</div><span>1</span><span>2</span><span>3</span><div>end</div></div>',\n      );\n    });\n  });\n\n  describe('Forced keyed children', () => {\n    it('Should always go keyed algorithm when parent has $HasKeyedChildren', () => {\n      const Collection = ({ children }) => (\n        <div $HasKeyedChildren>{children}</div>\n      );\n\n      render(\n        <Collection>\n          <div key=\"1\">1</div>\n          <div key=\"2\">2</div>\n          <div key=\"3\">3</div>\n        </Collection>,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div>1</div><div>2</div><div>3</div></div>',\n      );\n\n      render(\n        <Collection>\n          <div key=\"3\">3</div>\n          <div key=\"2\">2</div>\n          <div key=\"1\">1</div>\n        </Collection>,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div>3</div><div>2</div><div>1</div></div>',\n      );\n\n      render(\n        <Collection>\n          <div key=\"3\">3</div>\n          <div key=\"2\">2</div>\n          <div key=\"11\">11</div>\n        </Collection>,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div>3</div><div>2</div><div>11</div></div>',\n      );\n    });\n\n    it('Should be able to swap from keyed to nonkeyed when nextNode no longer is keyed', () => {\n      const CollectionKeyed = ({ children }) => (\n        <div $HasKeyedChildren>{children}</div>\n      );\n\n      const CollectionNonKeyed = ({ children }) => (\n        <div $HasNonKeyedChildren>{children}</div>\n      );\n\n      render(\n        <CollectionKeyed>\n          <div key=\"1\">1</div>\n          <div key=\"2\">2</div>\n          <div key=\"3\">3</div>\n        </CollectionKeyed>,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div>1</div><div>2</div><div>3</div></div>',\n      );\n\n      render(\n        <CollectionNonKeyed>\n          <div>3</div>\n          <div>2</div>\n        </CollectionNonKeyed>,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div>3</div><div>2</div></div>',\n      );\n\n      render(\n        <CollectionKeyed>\n          <div key=\"3\">3</div>\n          <div key=\"2\">2</div>\n          <div key=\"11\">11</div>\n        </CollectionKeyed>,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div>3</div><div>2</div><div>11</div></div>',\n      );\n    });\n\n    it('Should handle previous being empty array', () => {\n      const CollectionKeyed = ({ children }) => (\n        <div $HasKeyedChildren>{children}</div>\n      );\n\n      const child = [];\n      render(<CollectionKeyed>{child}</CollectionKeyed>, container);\n\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      render(\n        <CollectionKeyed>\n          <div key=\"1\">1</div>\n          <div key=\"2\">2</div>\n          <div key=\"3\">3</div>\n        </CollectionKeyed>,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div>1</div><div>2</div><div>3</div></div>',\n      );\n    });\n\n    it('Should handle next being empty array', () => {\n      const CollectionKeyed = ({ children }) => (\n        <div $HasKeyedChildren>{children}</div>\n      );\n\n      render(\n        <CollectionKeyed>\n          <div key=\"1\">1</div>\n          <div key=\"2\">2</div>\n          <div key=\"3\">3</div>\n        </CollectionKeyed>,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div>1</div><div>2</div><div>3</div></div>',\n      );\n\n      const child = [];\n      render(<CollectionKeyed>{child}</CollectionKeyed>, container);\n\n      expect(container.innerHTML).toEqual('<div></div>');\n    });\n\n    it('Should handle last/next being empty', () => {\n      const CollectionKeyed = ({ children }) => (\n        <div $HasKeyedChildren>{children}</div>\n      );\n\n      const child = [];\n      render(<CollectionKeyed>{child}</CollectionKeyed>, container);\n\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      const childB = [];\n\n      render(<CollectionKeyed>{childB}</CollectionKeyed>, container);\n\n      expect(container.innerHTML).toEqual('<div></div>');\n    });\n  });\n\n  describe('Unmount behavior in lists', () => {\n    it('Should not call unmount when changing list length', () => {\n      class UnMountTest extends Component {\n        public componentWillUnmount() {\n          // Should not be here\n        }\n\n        public render() {\n          return <span>1</span>;\n        }\n      }\n\n      interface ParentProps {\n        firstClassCitizenIsBack?: boolean;\n      }\n\n      class Parent extends Component<ParentProps> {\n        public render() {\n          let firstClassCitizen = null;\n          if (this.props.firstClassCitizenIsBack) {\n            firstClassCitizen = <div>b</div>;\n          }\n\n          // variable for debugging\n          const node = (\n            <div>\n              <div>a</div>\n              {firstClassCitizen}\n              <UnMountTest />\n              <div>C</div>\n            </div>\n          );\n\n          return node;\n        }\n      }\n\n      const spyUnmount = spyOn(UnMountTest.prototype, 'componentWillUnmount');\n\n      render(<Parent firstClassCitizenIsBack={false} />, container); // initial render\n      expect(container.innerHTML).toEqual(\n        '<div><div>a</div><span>1</span><div>C</div></div>',\n      );\n      expect(spyUnmount).not.toHaveBeenCalled();\n\n      render(<Parent firstClassCitizenIsBack={true} />, container);\n      expect(container.innerHTML).toEqual(\n        '<div><div>a</div><div>b</div><span>1</span><div>C</div></div>',\n      );\n      expect(spyUnmount).not.toHaveBeenCalled();\n    });\n  });\n\n  describe('Children lifecycle with fastUnmount', () => {\n    it('Should call componentWillUnmount for children', (done) => {\n      let toggle;\n\n      interface WrapperState {\n        bool: boolean;\n      }\n\n      class Wrapper extends Component<unknown, WrapperState> {\n        public state: WrapperState;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            bool: true,\n          };\n\n          toggle = () => {\n            this.setState({\n              bool: !this.state.bool,\n            });\n          };\n        }\n\n        public render() {\n          return (\n            <div>\n              <span>foobar</span>\n              {this.state.bool ? <FooBar /> : null}\n            </div>\n          );\n        }\n      }\n\n      interface FoobarState {\n        text: string;\n      }\n\n      class FooBar extends Component<unknown, FoobarState> {\n        public state: FoobarState;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            text: 'initial',\n          };\n        }\n\n        public componentWillUnmount() {}\n\n        public componentWillMount() {}\n\n        public render() {\n          return <span>{this.state.text}</span>;\n        }\n      }\n\n      render(<Wrapper />, container);\n\n      const unMountSpy = spyOn(FooBar.prototype, 'componentWillUnmount');\n      const mountSpy = spyOn(FooBar.prototype, 'componentWillMount');\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>foobar</span><span>initial</span></div>',\n      );\n\n      mountSpy.calls.reset();\n      unMountSpy.calls.reset();\n\n      toggle(); // Unmount child component\n      setTimeout(() => {\n        expect(container.innerHTML).toEqual('<div><span>foobar</span></div>');\n\n        expect(unMountSpy).toHaveBeenCalledTimes(1);\n        expect(mountSpy).not.toHaveBeenCalled();\n        done();\n      }, 10);\n    });\n\n    it('Should call componentWillUnmount for nested children', (done) => {\n      let toggle;\n\n      interface WrapperState {\n        bool: boolean;\n      }\n\n      class Wrapper extends Component<unknown, WrapperState> {\n        public state: WrapperState;\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            bool: true,\n          };\n\n          toggle = () => {\n            this.setState({\n              bool: !this.state.bool,\n            });\n          };\n        }\n\n        public render() {\n          return (\n            <div>\n              <span>foobar</span>\n              {this.state.bool ? <FooBar /> : null}\n            </div>\n          );\n        }\n      }\n\n      class FooBar extends Component {\n        public render() {\n          return (\n            <span>\n              <Test />\n            </span>\n          );\n        }\n      }\n\n      class Test extends Component {\n        public componentWillUnmount() {}\n\n        public componentWillMount() {}\n\n        public render() {\n          return <em>f</em>;\n        }\n      }\n\n      render(<Wrapper />, container);\n\n      const unMountSpy = spyOn(Test.prototype, 'componentWillUnmount');\n      const mountSpy = spyOn(Test.prototype, 'componentWillMount');\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>foobar</span><span><em>f</em></span></div>',\n      );\n\n      mountSpy.calls.reset();\n      unMountSpy.calls.reset();\n\n      toggle(); // Unmount child component\n      setTimeout(() => {\n        expect(container.innerHTML).toEqual('<div><span>foobar</span></div>');\n\n        expect(unMountSpy).toHaveBeenCalledTimes(1);\n        expect(mountSpy).not.toHaveBeenCalled();\n        done();\n      }, 10);\n    });\n\n    it('Should call componentWillUnmount for nested children #2', (done) => {\n      let toggle;\n\n      interface WrapperState {\n        bool: boolean;\n      }\n\n      class Wrapper extends Component<unknown, WrapperState> {\n        public state: WrapperState;\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            bool: true,\n          };\n\n          toggle = () => {\n            this.setState({\n              bool: !this.state.bool,\n            });\n          };\n        }\n\n        public render() {\n          return (\n            <div>\n              <span>foobar</span>\n              {this.state.bool ? <FooBar /> : null}\n            </div>\n          );\n        }\n      }\n\n      class FooBar extends Component {\n        public render() {\n          return (\n            <span>\n              <Test />\n              <Foo />\n            </span>\n          );\n        }\n      }\n\n      class Test extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <em>f</em>;\n        }\n      }\n\n      class Foo extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <em>f</em>;\n        }\n      }\n\n      render(<Wrapper />, container);\n\n      const unMountSpy = spyOn(Test.prototype, 'componentWillUnmount');\n      const unMountSpy2 = spyOn(Foo.prototype, 'componentWillUnmount');\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>foobar</span><span><em>f</em><em>f</em></span></div>',\n      );\n\n      unMountSpy2.calls.reset();\n      unMountSpy.calls.reset();\n\n      toggle(); // Unmount child component\n      setTimeout(() => {\n        expect(container.innerHTML).toEqual('<div><span>foobar</span></div>');\n        expect(unMountSpy2).toHaveBeenCalledTimes(1);\n        expect(unMountSpy).toHaveBeenCalledTimes(1);\n        done();\n      }, 10);\n    });\n\n    it('Should call componentWillUnmount for deeply nested children', (done) => {\n      let toggle;\n\n      interface WrapperState {\n        bool: boolean;\n      }\n\n      class Wrapper extends Component<unknown, WrapperState> {\n        public state: WrapperState;\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            bool: true,\n          };\n\n          toggle = () => {\n            this.setState({\n              bool: !this.state.bool,\n            });\n          };\n        }\n\n        public render() {\n          return (\n            <div>\n              <span>foobar</span>\n              {this.state.bool ? <FooBar /> : null}\n            </div>\n          );\n        }\n      }\n\n      class FooBar extends Component {\n        public render() {\n          return (\n            <span>\n              <span>\n                <span>\n                  <span>\n                    <Test />\n                  </span>\n                </span>\n              </span>\n            </span>\n          );\n        }\n      }\n\n      class Test extends Component {\n        public render() {\n          return <Test2 />;\n        }\n      }\n\n      class Test2 extends Component {\n        public render() {\n          return <Test4 />;\n        }\n      }\n\n      class Test4 extends Component {\n        public render() {\n          return (\n            <div>\n              <span />\n              <Test5 />\n              <span />\n            </div>\n          );\n        }\n      }\n\n      class Test5 extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <h1>ShouldUnMountMe</h1>;\n        }\n      }\n\n      render(<Wrapper />, container);\n\n      const unMountSpy = spyOn(Test5.prototype, 'componentWillUnmount');\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>foobar</span><span><span><span><span><div><span></span><h1>ShouldUnMountMe</h1><span></span></div></span></span></span></span></div>',\n      );\n\n      unMountSpy.calls.reset();\n\n      toggle(); // Unmount child component\n      setTimeout(() => {\n        expect(container.innerHTML).toEqual('<div><span>foobar</span></div>');\n        expect(unMountSpy).toHaveBeenCalledTimes(1);\n        done();\n      }, 10);\n    });\n\n    it('Should call componentWillUnmount for parent when children dont have componentWIllUnmount', (done) => {\n      class Wrapper extends Component {\n        constructor(props) {\n          super(props);\n        }\n\n        public componentWillUnmount() {}\n\n        public render() {\n          return (\n            <div>\n              <span>foobar</span>\n              <FooBar />\n            </div>\n          );\n        }\n      }\n\n      class FooBar extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return (\n            <span>\n              <Test />\n            </span>\n          );\n        }\n      }\n\n      class Test extends Component {\n        public render() {\n          return <em>f</em>;\n        }\n      }\n\n      render(<Wrapper />, container);\n\n      const unMountSpy = spyOn(Wrapper.prototype, 'componentWillUnmount');\n      const unMountSpy2 = spyOn(FooBar.prototype, 'componentWillUnmount');\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>foobar</span><span><em>f</em></span></div>',\n      );\n\n      unMountSpy.calls.reset();\n      unMountSpy2.calls.reset();\n\n      render(null, container);\n      setTimeout(() => {\n        expect(container.innerHTML).toEqual('');\n\n        expect(unMountSpy).toHaveBeenCalledTimes(1);\n        expect(unMountSpy2).toHaveBeenCalledTimes(1);\n        done();\n      }, 10);\n    });\n\n    it('Should fastUnmount child component when only parent has unmount callback', (done) => {\n      interface WrapperProps {\n        kill: boolean;\n      }\n\n      class Wrapper extends Component<WrapperProps> {\n        constructor(props) {\n          super(props);\n        }\n\n        public componentWillUnmount() {}\n\n        public render() {\n          return (\n            <div>\n              <span>foobar</span>\n              <FooBar kill={this.props.kill} />\n            </div>\n          );\n        }\n      }\n\n      interface FoobarProps {\n        kill: boolean;\n      }\n\n      class FooBar extends Component<FoobarProps> {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <span>{!this.props.kill ? <Test /> : null}</span>;\n        }\n      }\n\n      class Test extends Component {\n        public render() {\n          return (\n            <em>\n              <FastUnMountThis />\n            </em>\n          );\n        }\n      }\n\n      let dirtyReference: FastUnMountThis | null = null;\n      let updateFastUnmountedComponent: (() => void) | null = null;\n\n      interface FastUnMountThisState {\n        text: string;\n      }\n\n      class FastUnMountThis extends Component<unknown, FastUnMountThisState> {\n        public state: FastUnMountThisState;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            text: 'aa',\n          };\n\n          dirtyReference = this;\n          updateFastUnmountedComponent = () => {\n            this.changeText();\n          };\n        }\n\n        public changeText() {\n          this.setState({\n            text: 'foo',\n          });\n        }\n\n        public render() {\n          return <pre onclick={function () {}}>{this.state.text}</pre>;\n        }\n      }\n\n      render(<Wrapper kill={false} />, container);\n\n      const unMountSpy = spyOn(Wrapper.prototype, 'componentWillUnmount');\n      const unMountSpy2 = spyOn(FooBar.prototype, 'componentWillUnmount');\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>foobar</span><span><em><pre>aa</pre></em></span></div>',\n      );\n\n      render(<Wrapper kill={true} />, container);\n\n      setTimeout(() => {\n        expect(container.innerHTML).toEqual(\n          '<div><span>foobar</span><span></span></div>',\n        );\n\n        expect(unMountSpy).not.toHaveBeenCalled();\n        expect(unMountSpy2).not.toHaveBeenCalled();\n\n        // This component is actually unmounted but fastUnmount skips unmount loop so unmounted remains false\n        expect(dirtyReference!.$UN).toEqual(true);\n        // Try to do setState and verify it doesn't fail\n        updateFastUnmountedComponent!();\n\n        setTimeout(() => {\n          expect(dirtyReference!.$UN).toEqual(true);\n          expect(container.innerHTML).toEqual(\n            '<div><span>foobar</span><span></span></div>',\n          );\n\n          done();\n        }, 10);\n      }, 10);\n    });\n\n    it('Should render call componentWillUnmount for children when later sibling has no lifecycle', () => {\n      class Parent extends Component {\n        constructor(props) {\n          super(props);\n        }\n\n        public componentWillUnmount() {}\n\n        public render() {\n          return (\n            <div>\n              <HasLife />\n              <NoLife />\n            </div>\n          );\n        }\n      }\n\n      // This should be able to fastUnmount\n      class NoLife extends Component {\n        public render() {\n          return <span>nolife</span>;\n        }\n      }\n\n      // This should have fastUnmount false\n      class HasLife extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <span>haslife</span>;\n        }\n      }\n\n      const unMountSpy = spyOn(Parent.prototype, 'componentWillUnmount');\n      const unMountSpy2 = spyOn(HasLife.prototype, 'componentWillUnmount');\n\n      render(<Parent />, container);\n\n      expect(unMountSpy).not.toHaveBeenCalled();\n      expect(unMountSpy2).not.toHaveBeenCalled();\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>haslife</span><span>nolife</span></div>',\n      );\n\n      render(null, container);\n\n      expect(unMountSpy).toHaveBeenCalledTimes(1);\n      expect(unMountSpy2).toHaveBeenCalledTimes(1);\n    });\n  });\n\n  describe('Children lifecycle with fastUnmount Functional Components', () => {\n    it('Should call componentWillUnmount for children', () => {\n      let mountCalls = 0;\n      let unMountCalls = 0;\n      const foobarLifecycle = {\n        componentWillMount: () => {\n          mountCalls++;\n        },\n        componentWillUnmount: () => {\n          unMountCalls++;\n        },\n      };\n\n      function Wrapper({ bool }) {\n        return (\n          <div>\n            <span>foobar</span>\n            {bool ? (\n              <FooBar\n                onComponentWillMount={foobarLifecycle.componentWillMount}\n                onComponentWillUnmount={foobarLifecycle.componentWillUnmount}\n              />\n            ) : null}\n          </div>\n        );\n      }\n\n      function FooBar() {\n        return <span>initial</span>;\n      }\n\n      render(<Wrapper bool={true} />, container);\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>foobar</span><span>initial</span></div>',\n      );\n\n      expect(mountCalls).toEqual(1);\n      expect(unMountCalls).toEqual(0);\n\n      render(<Wrapper bool={false} />, container); // Unmount child component\n      expect(container.innerHTML).toEqual('<div><span>foobar</span></div>');\n\n      expect(mountCalls).toEqual(1);\n      expect(unMountCalls).toEqual(1);\n    });\n\n    it('Should call componentWillUnmount for nested children', () => {\n      let unMountCalls = 0;\n      let mountCalls = 0;\n\n      const testLifeCycle = {\n        componentWillMount: () => {\n          mountCalls++;\n        },\n        componentWillUnmount: () => {\n          unMountCalls++;\n        },\n      };\n\n      function Wrapper({ bool }) {\n        return (\n          <div>\n            <span>foobar</span>\n            {bool ? <FooBar /> : null}\n          </div>\n        );\n      }\n\n      function FooBar() {\n        return (\n          <span>\n            <Test\n              onComponentWillMount={testLifeCycle.componentWillMount}\n              onComponentWillUnmount={testLifeCycle.componentWillUnmount}\n            />\n          </span>\n        );\n      }\n\n      function Test() {\n        return <em>f</em>;\n      }\n\n      render(<Wrapper bool={true} />, container);\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>foobar</span><span><em>f</em></span></div>',\n      );\n\n      expect(mountCalls).toEqual(1);\n      expect(unMountCalls).toEqual(0);\n\n      render(<Wrapper bool={false} />, container); // Unmount child component\n      expect(container.innerHTML).toEqual('<div><span>foobar</span></div>');\n\n      expect(mountCalls).toEqual(1);\n      expect(unMountCalls).toEqual(1);\n    });\n\n    it('Should call componentWillUnmount for nested children #2', () => {\n      let unMountTest = 0;\n      let unMountFoo = 0;\n\n      const testLifeCycle = {\n        componentWillUnmount: () => {\n          unMountTest++;\n        },\n      };\n\n      const fooLifecycle = {\n        componentWillUnmount: () => {\n          unMountFoo++;\n        },\n      };\n\n      function Wrapper({ bool }) {\n        return (\n          <div>\n            <span>foobar</span>\n            {bool ? <FooBar /> : null}\n          </div>\n        );\n      }\n\n      function FooBar() {\n        return (\n          <span>\n            <Test onComponentWillUnmount={testLifeCycle.componentWillUnmount} />\n            <Foo onComponentWillUnmount={fooLifecycle.componentWillUnmount} />\n          </span>\n        );\n      }\n\n      function Test() {\n        return <em>f</em>;\n      }\n\n      function Foo() {\n        return <em>f</em>;\n      }\n\n      render(<Wrapper bool={true} />, container);\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>foobar</span><span><em>f</em><em>f</em></span></div>',\n      );\n\n      render(<Wrapper bool={false} />, container);\n      expect(container.innerHTML).toEqual('<div><span>foobar</span></div>');\n      expect(unMountTest).toEqual(1);\n      expect(unMountFoo).toEqual(1);\n    });\n\n    it('Should call componentWillUnmount for deeply nested children', () => {\n      let unMountTest = 0;\n\n      const testLifecycle = {\n        componentWillUnmount: () => {\n          unMountTest++;\n        },\n      };\n\n      function Wrapper({ bool }) {\n        return (\n          <div>\n            <span>foobar</span>\n            {bool ? <FooBar /> : null}\n          </div>\n        );\n      }\n\n      function FooBar() {\n        return (\n          <span>\n            <span>\n              <span>\n                <span>\n                  <Test />\n                </span>\n              </span>\n            </span>\n          </span>\n        );\n      }\n\n      function Test() {\n        return <Test2 />;\n      }\n\n      function Test2() {\n        return <Test4 />;\n      }\n\n      function Test4() {\n        return (\n          <div>\n            <span />\n            <Test5\n              onComponentWillUnmount={testLifecycle.componentWillUnmount}\n            />\n            <span />\n          </div>\n        );\n      }\n\n      function Test5() {\n        return <h1>ShouldUnMountMe</h1>;\n      }\n\n      render(<Wrapper bool={true} />, container);\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>foobar</span><span><span><span><span><div><span></span><h1>ShouldUnMountMe</h1><span></span></div></span></span></span></span></div>',\n      );\n\n      render(<Wrapper bool={false} />, container);\n      expect(container.innerHTML).toEqual('<div><span>foobar</span></div>');\n\n      expect(unMountTest).toEqual(1);\n    });\n\n    it('Should call componentWillUnmount for parent when children dont have componentWIllUnmount', (done) => {\n      let unMountTest = 0;\n      let unMountTwoTest = 0;\n\n      const testLifecycle = {\n        componentWillUnmount: () => {\n          unMountTest++;\n        },\n        componentWillUnmountTwo: () => {\n          unMountTwoTest++;\n        },\n      };\n\n      function Wrapper() {\n        return (\n          <div>\n            <span>foobar</span>\n            <FooBar\n              onComponentWillUnmount={testLifecycle.componentWillUnmountTwo}\n            />\n          </div>\n        );\n      }\n\n      function FooBar() {\n        return (\n          <span>\n            <Test />\n          </span>\n        );\n      }\n\n      function Test() {\n        return <em>f</em>;\n      }\n\n      render(\n        <Wrapper onComponentWillUnmount={testLifecycle.componentWillUnmount} />,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>foobar</span><span><em>f</em></span></div>',\n      );\n\n      render(null, container);\n      setTimeout(() => {\n        expect(container.innerHTML).toEqual('');\n\n        expect(unMountTest).toEqual(1);\n        expect(unMountTwoTest).toEqual(1);\n        done();\n      }, 10);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/clonenode.spec.tsx",
    "content": "import { render } from 'inferno';\n\ndescribe('CloneVNode use cases', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should be able to render hoisted node', () => {\n    const a = ['foo', 'bar'];\n\n    render(<div>{[a, a, a, a]}</div>, container);\n\n    expect(container.innerHTML).toEqual('<div>foobarfoobarfoobarfoobar</div>');\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/columnrender.spec.tsx",
    "content": "import { Component, render } from 'inferno';\nimport { isNullOrUndef } from 'inferno-shared';\nimport Spy = jasmine.Spy;\n\ndescribe('Columns like tests - (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('Column-like tests', () => {\n    function buildTestCases(row, item, suffix) {\n      return [\n        {\n          initial: [\n            row(1, item(1, 1), item(2, 2)),\n            row(2, item(3, 3), item(4, 4)),\n          ],\n          name: 'add one column -' + suffix,\n          update: [\n            row(1, item(1, 1), item(2, 2)),\n            row(2, item(3, 3), item(4, 4)),\n            row(3, item(5, 5)),\n          ],\n        },\n        {\n          initial: [\n            row(1, item(1, 1), item(2, 2)),\n            row(2, item(3, 3), item(4, 4)),\n          ],\n          name: 'add one item -' + suffix,\n          update: [\n            row(1, item(1, 1), item(2, 2), item(5, 5)),\n            row(2, item(3, 3), item(4, 4)),\n          ],\n        },\n        {\n          initial: [\n            row(1, item(1, 1), item(2, 2)),\n            row(2, item(3, 3), item(4, 4)),\n          ],\n          name: 'add one column and item -' + suffix,\n          update: [\n            row(1, item(1, 1), item(2, 2)),\n            row(2, item(3, 3), item(4, 4), item(6, 6)),\n            row(3, item(5, 5)),\n          ],\n        },\n        {\n          initial: [\n            row(1, item(1, 1), item(2, 2)),\n            row(2, item(3, 3), item(4, 4)),\n          ],\n          name: 'swap all items -' + suffix,\n          update: [\n            row(1, item(2, 2), item(1, 1)),\n            row(2, item(4, 4), item(3, 3)),\n          ],\n        },\n        {\n          initial: [\n            row(1, item(1, 1), item(2, 2)),\n            row(2, item(3, 3), item(4, 4)),\n          ],\n          name: 'remove first item -' + suffix,\n          update: [row(1, item(2, 2)), row(2, item(4, 4))],\n        },\n        {\n          initial: [\n            row(1, item(1, 1), item(2, 2)),\n            row(2, item(3, 3), item(4, 4)),\n          ],\n          name: 'remove last item -' + suffix,\n          update: [row(1, item(1, 1)), row(2, item(3, 3))],\n        },\n        {\n          initial: [\n            row(1, item(1, 1), item(2, 2)),\n            row(2, item(3, 3), item(4, 4)),\n          ],\n          name: 'remove all items-' + suffix,\n          update: [row(1), row(2)],\n        },\n        {\n          initial: [\n            row(1, item(1, 1), item(2, 2)),\n            row(2, item(3, 3), item(4, 4)),\n          ],\n          name: 'remove all columns-' + suffix,\n          update: [],\n        },\n      ];\n    }\n\n    function filterPlaceholders(_nodes) {\n      const nodes = [].slice.apply(_nodes);\n      let len = nodes.length;\n      let i = 0;\n\n      while (i < len) {\n        const node = nodes[i];\n\n        if (node.nodeType === 3 && node.nodeValue === '') {\n          nodes.splice(i, 1);\n          len--;\n        }\n        i++;\n      }\n      return nodes;\n    }\n\n    function verifyRenderResult(columns, _container) {\n      // Verify root\n      const root = _container.firstChild;\n      const rootChildNodes = filterPlaceholders(root.childNodes);\n\n      expect(rootChildNodes.length).toBe(columns.length);\n      // Verify columns\n      for (let i = 0; i < rootChildNodes.length; i++) {\n        const columnRoot = rootChildNodes[i];\n        const columnChildNodes = filterPlaceholders(columnRoot.childNodes);\n\n        expect(columnChildNodes.length).toBe(columns[i].items.length + 1);\n        expect(columnRoot.firstChild.innerHTML).toBe('column');\n\n        // Verify items\n        // Skip first - its hardcoded\n        for (let j = 1; j < columnChildNodes.length; j++) {\n          const itemRoot = columnChildNodes[j];\n          expect(itemRoot.innerHTML).toBe(\n            columns[i].items[j - 1].text.toString(),\n          );\n        }\n      }\n    }\n\n    function getDifferentObjects(arr1, arr2) {\n      return arr1.filter(function (obj) {\n        return !arr2.some(function (obj2) {\n          return obj._testKey === obj2._testKey;\n        });\n      });\n    }\n\n    function getSameObjects(arr1, arr2) {\n      return arr1.filter(function (obj) {\n        return arr2.some(function (obj2) {\n          return obj._testKey === obj2._testKey;\n        });\n      });\n    }\n\n    describe('columns KEYED', () => {\n      // Item Keyed\n      function BuildItemKeyed(key, text) {\n        return { _testKey: key, id: key, text };\n      }\n\n      // Row Keyed\n      function BuildRowKeyed(key, ...items) {\n        return { _testKey: key, id: key, items };\n      }\n\n      const keyedTests = buildTestCases(BuildRowKeyed, BuildItemKeyed, 'KEYED');\n\n      interface ItemKeyedProps {\n        text?: string;\n      }\n\n      class ItemKeyed extends Component<ItemKeyedProps> {\n        constructor(props) {\n          super(props);\n        }\n\n        public componentWillUpdate() {}\n\n        public componentWillMount() {}\n\n        public componentWillUnmount() {}\n\n        public render() {\n          return <div>{this.props.text}</div>;\n        }\n      }\n\n      interface ColumnKeyedProps {\n        items: Array<{ id: string; text: string }>;\n      }\n\n      class ColumnKeyed extends Component<ColumnKeyedProps> {\n        constructor(props) {\n          super(props);\n        }\n\n        public componentWillUpdate() {}\n\n        public componentWillMount() {}\n\n        public componentWillUnmount() {}\n\n        public render() {\n          const items = this.props.items;\n\n          return (\n            <div>\n              <span key=\"column\">column</span>\n              {items.map((item) => (\n                <ItemKeyed key={item.id} text={item.text} />\n              ))}\n            </div>\n          );\n        }\n      }\n\n      const ViewKeyed = ({ columns }) => (\n        <div>\n          {columns.map((column) => (\n            <ColumnKeyed key={column.id} items={column.items} />\n          ))}\n        </div>\n      );\n\n      let mountedColumnSpy: Spy = null as unknown as Spy;\n      let unmountColumnSpy = null as unknown as Spy;\n      let updateColumnSpy = null as unknown as Spy;\n      let mountedItemSpy = null as unknown as Spy;\n      let unmountItemSpy = null as unknown as Spy;\n      let updateItemSpy = null as unknown as Spy;\n\n      beforeEach(function () {\n        mountedColumnSpy = spyOn(ColumnKeyed.prototype, 'componentWillMount');\n        unmountColumnSpy = spyOn(ColumnKeyed.prototype, 'componentWillUnmount');\n        updateColumnSpy = spyOn(ColumnKeyed.prototype, 'componentWillUpdate');\n        mountedItemSpy = spyOn(ItemKeyed.prototype, 'componentWillMount');\n        unmountItemSpy = spyOn(ItemKeyed.prototype, 'componentWillUnmount');\n        updateItemSpy = spyOn(ItemKeyed.prototype, 'componentWillUpdate');\n      });\n\n      afterEach(function () {\n        mountedColumnSpy.calls.reset();\n        unmountColumnSpy.calls.reset();\n        updateColumnSpy.calls.reset();\n        mountedItemSpy.calls.reset();\n        unmountItemSpy.calls.reset();\n        updateItemSpy.calls.reset();\n      });\n\n      for (const testCase of keyedTests) {\n        it('Should ' + testCase.name, () => {\n          const columnsToBeAdded = getDifferentObjects(\n            testCase.update,\n            testCase.initial,\n          );\n          const columnsToUpdate = getSameObjects(\n            testCase.update,\n            testCase.initial,\n          );\n          const columnsToRemove = getDifferentObjects(\n            testCase.initial,\n            testCase.update,\n          );\n\n          let itemsToBeAdded = [];\n          let itemsToUpdate = [];\n          let itemsToRemove = [];\n          let initialItemsCount = 0;\n\n          for (\n            let i = 0;\n            i < testCase.update.length || i < testCase.initial.length;\n            i++\n          ) {\n            const updateColumns = testCase.update[i];\n            const intialColumns = testCase.initial[i];\n\n            if (!isNullOrUndef(updateColumns)) {\n              if (!isNullOrUndef(intialColumns)) {\n                itemsToBeAdded = itemsToBeAdded.concat(\n                  getDifferentObjects(updateColumns.items, intialColumns.items),\n                );\n                itemsToRemove = itemsToRemove.concat(\n                  getDifferentObjects(intialColumns.items, updateColumns.items),\n                );\n                itemsToUpdate = itemsToUpdate.concat(\n                  getSameObjects(updateColumns.items, intialColumns.items),\n                );\n                initialItemsCount += intialColumns.items.length;\n              } else {\n                itemsToBeAdded = itemsToBeAdded.concat(updateColumns.items);\n              }\n            } else {\n              if (!isNullOrUndef(intialColumns)) {\n                initialItemsCount += intialColumns.items.length;\n                itemsToRemove = itemsToRemove.concat(intialColumns.items);\n              } else {\n                // Do nothing\n              }\n            }\n          }\n\n          // Do initial render\n          render(<ViewKeyed columns={testCase.initial} />, container);\n          verifyRenderResult(testCase.initial, container);\n          expect(mountedColumnSpy.calls.count()).toBe(testCase.initial.length); // Initial all mounted\n          expect(unmountColumnSpy.calls.count()).toBe(0); // Initial render none unmounted\n          expect(updateColumnSpy.calls.count()).toBe(0); // Initial render none to update\n\n          expect(mountedItemSpy.calls.count()).toBe(initialItemsCount); // Initial render - mount all items once\n          expect(updateItemSpy.calls.count()).toBe(0); // Initial render none to update\n          expect(unmountItemSpy.calls.count()).toBe(0); // Initial render none unmounted\n\n          // reset call counts\n          mountedColumnSpy.calls.reset();\n          unmountColumnSpy.calls.reset();\n          updateColumnSpy.calls.reset();\n          mountedItemSpy.calls.reset();\n          updateItemSpy.calls.reset();\n          unmountItemSpy.calls.reset();\n\n          // Do update\n          render(<ViewKeyed columns={testCase.update} />, container);\n          verifyRenderResult(testCase.update, container);\n\n          expect(mountedColumnSpy.calls.count()).toBe(columnsToBeAdded.length); // mount count should equal to added count\n          expect(unmountColumnSpy.calls.count()).toBe(columnsToRemove.length); // Initial render none unmounted\n          expect(updateColumnSpy.calls.count()).toBe(columnsToUpdate.length); // Initial render none unmounted\n          expect(mountedItemSpy.calls.count()).toBe(itemsToBeAdded.length); // Initial render - mount all items once\n          expect(updateItemSpy.calls.count()).toBe(itemsToUpdate.length); // Initial render none to update\n          expect(unmountItemSpy.calls.count()).toBe(itemsToRemove.length); // Initial render none unmounted\n        });\n      }\n    });\n\n    describe('columns NON-KEYED', () => {\n      // Item Keyed\n      function BuildItem(key, text) {\n        return { _testKey: key, text };\n      }\n\n      // Row Keyed\n      function BuildRow(key, ...items) {\n        return { _testKey: key, items };\n      }\n\n      const nonKeyedTestCases = buildTestCases(\n        BuildRow,\n        BuildItem,\n        'NON-KEYED',\n      );\n\n      interface ItemProps {\n        text: string;\n      }\n\n      class Item extends Component<ItemProps> {\n        constructor(props) {\n          super(props);\n        }\n\n        public componentWillUpdate() {}\n\n        public componentWillMount() {}\n\n        public componentWillUnmount() {}\n\n        public render() {\n          return <div>{this.props.text}</div>;\n        }\n      }\n\n      interface ColumnProps {\n        items: Array<{ text: string }>;\n      }\n\n      class Column extends Component<ColumnProps> {\n        constructor(props) {\n          super(props);\n        }\n\n        public componentWillUpdate() {}\n\n        public componentWillMount() {}\n\n        public componentWillUnmount() {}\n\n        public render() {\n          const items = this.props.items;\n\n          return (\n            <div>\n              <span>column</span>\n              {items.map((item) => (\n                <Item text={item.text} />\n              ))}\n            </div>\n          );\n        }\n      }\n\n      const View = ({ columns }) => (\n        <div>\n          {columns.map((column) => (\n            <Column items={column.items} />\n          ))}\n        </div>\n      );\n\n      let mountedColumnSpy = null as unknown as Spy;\n      let unmountColumnSpy = null as unknown as Spy;\n      let updateColumnSpy = null as unknown as Spy;\n      let mountedItemSpy = null as unknown as Spy;\n      let unmountItemSpy = null as unknown as Spy;\n      let updateItemSpy = null as unknown as Spy;\n\n      beforeEach(function () {\n        mountedColumnSpy = spyOn(Column.prototype, 'componentWillMount');\n        unmountColumnSpy = spyOn(Column.prototype, 'componentWillUnmount');\n        updateColumnSpy = spyOn(Column.prototype, 'componentWillUpdate');\n        mountedItemSpy = spyOn(Item.prototype, 'componentWillMount');\n        unmountItemSpy = spyOn(Item.prototype, 'componentWillUnmount');\n        updateItemSpy = spyOn(Item.prototype, 'componentWillUpdate');\n      });\n\n      afterEach(function () {\n        mountedColumnSpy.calls.reset();\n        unmountColumnSpy.calls.reset();\n        updateColumnSpy.calls.reset();\n        mountedItemSpy.calls.reset();\n        unmountItemSpy.calls.reset();\n        updateItemSpy.calls.reset();\n      });\n\n      for (const testCase of nonKeyedTestCases) {\n        it('Should ' + testCase.name, () => {\n          const columnsToBeAdded = getDifferentObjects(\n            testCase.update,\n            testCase.initial,\n          );\n          const columnsToUpdate = getSameObjects(\n            testCase.update,\n            testCase.initial,\n          );\n          const columnsToRemove = getDifferentObjects(\n            testCase.initial,\n            testCase.update,\n          );\n\n          let itemsToBeAdded = [];\n          let itemsToUpdate = [];\n          let itemsToRemove = [];\n          let initialItemsCount = 0;\n\n          for (\n            let i = 0;\n            i < testCase.update.length || i < testCase.initial.length;\n            i++\n          ) {\n            const updateColumns = testCase.update[i];\n            const intialColumns = testCase.initial[i];\n\n            if (!isNullOrUndef(updateColumns)) {\n              if (!isNullOrUndef(intialColumns)) {\n                itemsToBeAdded = itemsToBeAdded.concat(\n                  getDifferentObjects(updateColumns.items, intialColumns.items),\n                );\n                itemsToRemove = itemsToRemove.concat(\n                  getDifferentObjects(intialColumns.items, updateColumns.items),\n                );\n                itemsToUpdate = itemsToUpdate.concat(\n                  getSameObjects(updateColumns.items, intialColumns.items),\n                );\n                initialItemsCount += intialColumns.items.length;\n              } else {\n                itemsToBeAdded = itemsToBeAdded.concat(updateColumns.items);\n              }\n            } else {\n              if (!isNullOrUndef(intialColumns)) {\n                initialItemsCount += intialColumns.items.length;\n                itemsToRemove = itemsToRemove.concat(intialColumns.items);\n              } else {\n                // Do nothing\n              }\n            }\n          }\n\n          // Do initial render\n          render(<View columns={testCase.initial} />, container);\n          verifyRenderResult(testCase.initial, container);\n          expect(mountedColumnSpy.calls.count()).toBe(testCase.initial.length); // Initial all mounted\n          expect(unmountColumnSpy.calls.count()).toBe(0); // Initial render none unmounted\n          expect(updateColumnSpy.calls.count()).toBe(0); // Initial render none to update\n\n          expect(mountedItemSpy.calls.count()).toBe(initialItemsCount); // Initial render - mount all items once\n          expect(updateItemSpy.calls.count()).toBe(0); // Initial render none to update\n          expect(unmountItemSpy.calls.count()).toBe(0); // Initial render none unmounted\n\n          // reset call counts\n          mountedColumnSpy.calls.reset();\n          unmountColumnSpy.calls.reset();\n          updateColumnSpy.calls.reset();\n          mountedItemSpy.calls.reset();\n          updateItemSpy.calls.reset();\n          unmountItemSpy.calls.reset();\n\n          // Do update\n          render(<View columns={testCase.update} />, container);\n          verifyRenderResult(testCase.update, container);\n\n          expect(mountedColumnSpy.calls.count()).toBe(columnsToBeAdded.length); // mount count should equal to added count\n          expect(unmountColumnSpy.calls.count()).toBe(columnsToRemove.length); // Initial render none unmounted\n          expect(updateColumnSpy.calls.count()).toBe(columnsToUpdate.length); // Initial render none unmounted\n          expect(mountedItemSpy.calls.count()).toBe(itemsToBeAdded.length); // Initial render - mount all items once\n          expect(updateItemSpy.calls.count()).toBe(itemsToUpdate.length); // Initial render none to update\n          expect(unmountItemSpy.calls.count()).toBe(itemsToRemove.length); // Initial render none unmounted\n        });\n      }\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/componentlifecycle.spec.tsx",
    "content": "import { Component, render, rerender } from 'inferno';\n\ndescribe('Component lifecycle', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('componentWillUpdate Should have nextProp in params and old variants in instance', () => {\n    let callCount = 0;\n\n    class Com extends Component<{ value: number }> {\n      public componentWillUpdate(nextProps) {\n        callCount++;\n        expect(this.props.value).toBe(1);\n        expect(nextProps.value).toBe(2);\n      }\n\n      public render() {\n        return <div>{this.props.value}</div>;\n      }\n    }\n\n    render(<Com value={1} />, container);\n\n    expect(container.innerHTML).toBe('<div>1</div>');\n\n    render(<Com value={2} />, container);\n\n    expect(callCount).toBe(1);\n    expect(container.innerHTML).toBe('<div>2</div>');\n  });\n\n  it('Current state in componentWillUpdate should not equal nextState if setState is called from componentWillReceiveProps', () => {\n    let doSomething;\n\n    class Child extends Component<{ active: boolean }, { active: boolean }> {\n      public state = {\n        active: false,\n      };\n\n      constructor() {\n        super();\n      }\n\n      public componentWillReceiveProps(nextProps) {\n        if (!this.props.active && nextProps.active) {\n          this.setState({\n            active: true,\n          });\n        }\n      }\n\n      public componentWillUpdate(_nextProps, nextState) {\n        expect(this.state.active).toBe(false);\n        expect(nextState.active).toBe(true);\n      }\n\n      public render() {\n        return <div>{this.state.active ? 'true' : 'false'}</div>;\n      }\n    }\n\n    class Parent extends Component<object, { active: boolean }> {\n      public state = {\n        active: false,\n      };\n\n      constructor() {\n        super();\n        doSomething = this._setActive = this._setActive.bind(this);\n      }\n\n      public _setActive() {\n        this.setState({\n          active: true,\n        });\n      }\n\n      public render() {\n        return (\n          <div>\n            <Child active={this.state.active} />\n          </div>\n        );\n      }\n    }\n\n    render(<Parent />, container);\n\n    expect(container.innerHTML).toBe('<div><div>false</div></div>');\n\n    doSomething();\n\n    rerender();\n\n    expect(container.innerHTML).toBe('<div><div>true</div></div>');\n  });\n\n  it('shouldComponentUpdate Should have nextProp in params and old variants in instance', () => {\n    let callCount = 0;\n\n    class Com extends Component<{ value: number }> {\n      public shouldComponentUpdate(nextProps) {\n        callCount++;\n        expect(this.props.value).toBe(1);\n        expect(nextProps.value).toBe(2);\n\n        return true;\n      }\n\n      public render() {\n        return <div>{this.props.value}</div>;\n      }\n    }\n\n    render(<Com value={1} />, container);\n\n    expect(container.innerHTML).toBe('<div>1</div>');\n\n    render(<Com value={2} />, container);\n\n    expect(callCount).toBe(1);\n    expect(container.innerHTML).toBe('<div>2</div>');\n  });\n\n  it('Should call componentWillUnmount before node is removed from DOM tree', () => {\n    class Parent extends Component<{ foo: boolean }> {\n      public render() {\n        if (this.props.foo) {\n          return (\n            <div>\n              <p>just to make it go removeAll</p>\n              <Child />\n            </div>\n          );\n        }\n\n        return (\n          <div>\n            <p>just to make it go removeAll</p>\n          </div>\n        );\n      }\n    }\n\n    class Child extends Component {\n      private element: Element;\n\n      public componentWillUnmount() {\n        // verify its not removed from DOM tree yet.\n        expect(\n          this.element.parentElement != null\n            ? this.element.parentElement.parentElement\n            : null,\n        ).toBe(container);\n      }\n\n      public render() {\n        return (\n          <div className=\"foobar\" ref={(el) => (this.element = el!)}>\n            1\n          </div>\n        );\n      }\n    }\n\n    render(<Parent foo={true} />, container);\n    expect(container.querySelectorAll('.foobar').length).toBe(1);\n    render(<Parent foo={false} />, container);\n    // Verify the specific div is removed now\n    expect(container.querySelectorAll('.foobar').length).toBe(0);\n  });\n\n  it('Should not fail if componentDidUpdate is undefined #922', () => {\n    let c;\n\n    class Com extends Component<{ value: number }> {\n      public componentDidUpdate(nextProps) {\n        expect(this.props.value).toBe(1);\n        expect(nextProps.value).toBe(2);\n\n        return true;\n      }\n\n      public render() {\n        return <div>{this.props.value}</div>;\n      }\n    }\n\n    render(\n      <Com\n        ref={(inst) => {\n          c = inst;\n        }}\n        value={1}\n      />,\n      container,\n    );\n\n    c.componentDidUpdate = undefined;\n\n    render(<Com ref={(inst) => (c = inst)} value={2} />, container);\n  });\n});\n\ndescribe('legacy life cycle', () => {\n  let consoleErrorStub;\n  let container;\n\n  beforeEach(() => {\n    consoleErrorStub = spyOn(console, 'error');\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should warn when mix legacy life cycle with new ones', () => {\n    // build the component and element to be rendered\n    class Foo extends Component {\n      // just added to force the warnings\n      static getDerivedStateFromProps() {}\n\n      componentWillMount() {}\n\n      componentWillReceiveProps() {}\n\n      componentWillUpdate() {}\n\n      render() {\n        return <div>Foo</div>;\n      }\n    }\n\n    const element = <Foo />;\n\n    // render the element\n    render(element, container);\n\n    // retrieve the arguments of all calls for console.error\n    // so multiple calls to console.error should not broke this test\n\n    expect(consoleErrorStub).toHaveBeenCalledTimes(1);\n\n    const message = consoleErrorStub.calls.argsFor(0)[0];\n    expect(message.includes('componentWillMount')).toBeTruthy();\n    expect(message.includes('componentWillReceiveProps')).toBeTruthy();\n    expect(message.includes('componentWillUpdate')).toBeTruthy();\n  });\n\n  it('should allow suppress legacy life cycles when mixed with new APIs', () => {\n    // build the component and element to be rendered\n    class Foo extends Component {\n      // just added to force the warnings\n      static getDerivedStateFromProps() {}\n\n      componentWillMount() {}\n\n      componentWillReceiveProps() {}\n\n      componentWillUpdate() {}\n\n      render() {\n        return <div>Foo</div>;\n      }\n    }\n\n    // suppress the warnings\n    // @ts-expect-error\n    Foo.prototype.componentWillMount.__suppressDeprecationWarning = true;\n    // @ts-expect-error\n    Foo.prototype.componentWillReceiveProps.__suppressDeprecationWarning = true;\n    // @ts-expect-error\n    Foo.prototype.componentWillUpdate.__suppressDeprecationWarning = true;\n\n    const element = <Foo />;\n    // render the element\n    render(element, container);\n\n    expect(console.error).toHaveBeenCalledTimes(0);\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/components2.spec.tsx",
    "content": "import { Component, render } from 'inferno';\n/* These must be in their own files for test to reproduce */\nimport { ParentFirstCommon } from './data/common-render/parentfirstcommon';\nimport { ParentSecondCommon } from './data/common-render/parentsecondcommon';\n\ndescribe('Components (JSX) #2', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    container.style.display = 'none';\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    document.body.removeChild(container);\n  });\n\n  describe('tracking DOM state', () => {\n    class ComponentA extends Component {\n      public render() {\n        return (\n          <div>\n            <span>Something</span>\n          </div>\n        );\n      }\n    }\n\n    class ComponentB extends Component {\n      public render() {\n        return (\n          <div>\n            <span>Something</span>\n          </div>\n        );\n      }\n    }\n\n    interface ComponentBWithStateChangeState {\n      text: string;\n    }\n\n    class ComponentBWithStateChange extends Component<\n      unknown,\n      ComponentBWithStateChangeState\n    > {\n      public state: ComponentBWithStateChangeState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          text: '',\n        };\n      }\n\n      public componentWillMount() {\n        this.setState({\n          text: 'newText',\n        });\n\n        this.setState({\n          text: 'newText2',\n        });\n      }\n\n      public render() {\n        return (\n          <div>\n            <span>{this.state.text}</span>\n          </div>\n        );\n      }\n    }\n\n    function ComA() {\n      return (\n        <div>\n          <span>Something</span>\n        </div>\n      );\n    }\n\n    function ComB() {\n      return (\n        <div>\n          <span>Something</span>\n        </div>\n      );\n    }\n\n    it('patching component A to component B, given they have the same children, should replace DOM tree ( for lifecycle ) with identical one', () => {\n      render(<ComponentA />, container);\n      expect(container.innerHTML).toBe('<div><span>Something</span></div>');\n      const trackElemDiv = container.firstChild;\n      const trackElemSpan = container.firstChild.firstChild;\n\n      render(<ComponentB />, container);\n      // These are same but not equal\n      expect(container.innerHTML).toBe('<div><span>Something</span></div>');\n      expect(container.firstChild === trackElemDiv).toBe(false);\n      expect(container.firstChild.firstChild === trackElemSpan).toBe(false);\n    });\n\n    it('patching component A to component B, given they have the same children, should not change the DOM tree when stateless components', () => {\n      render(<ComA />, container);\n      expect(container.innerHTML).toBe('<div><span>Something</span></div>');\n      const trackElemDiv = container.firstChild;\n      const trackElemSpan = container.firstChild.firstChild;\n\n      render(<ComB />, container);\n      expect(container.innerHTML).toBe('<div><span>Something</span></div>');\n\n      expect(container.firstChild === trackElemDiv).toBe(false);\n      expect(container.firstChild.firstChild === trackElemSpan).toBe(false);\n    });\n\n    it('Should not crash when ComB does setState while changing', () => {\n      render(<ComponentA />, container);\n      expect(container.innerHTML).toBe('<div><span>Something</span></div>');\n      const trackElemDiv = container.firstChild;\n      const trackElemSpan = container.firstChild.firstChild;\n\n      render(<ComponentBWithStateChange />, container);\n      // These are same but not equal\n      expect(container.innerHTML).toBe('<div><span>newText2</span></div>');\n      expect(container.firstChild === trackElemDiv).toBe(false);\n      expect(container.firstChild.firstChild === trackElemSpan).toBe(false);\n    });\n  });\n\n  describe('Inheritance with common render', () => {\n    interface ChildProps {\n      name: string;\n    }\n\n    interface ChildState {\n      data: string;\n    }\n\n    class Child extends Component<ChildProps, ChildState> {\n      public state: ChildState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = { data: '' };\n\n        this._update = this._update.bind(this);\n      }\n\n      public _update() {\n        this.setState({\n          data: 'bar',\n        });\n      }\n\n      public componentWillMount() {\n        this.setState({\n          data: 'foo',\n        });\n      }\n\n      public render() {\n        return (\n          <div onclick={this._update}>\n            {this.props.name}\n            {this.state.data}\n          </div>\n        );\n      }\n    }\n\n    class ParentBase extends Component {\n      protected foo: string;\n\n      public render() {\n        return (\n          <div>\n            <Child name={this.foo} />\n          </div>\n        );\n      }\n    }\n\n    class ParentFirst extends ParentBase {\n      constructor(props) {\n        super(props);\n\n        this.foo = 'First';\n      }\n    }\n\n    class ParentSecond extends ParentBase {\n      constructor(props) {\n        super(props);\n\n        this.foo = 'Second';\n      }\n    }\n\n    // For some reason this one breaks but if components are imported separately, it works\n    it('Should not reuse children if parent changes #1', () => {\n      render(<ParentFirst />, container);\n      expect(container.innerHTML).toBe('<div><div>Firstfoo</div></div>');\n      container.firstChild.firstChild.click();\n\n      expect(container.innerHTML).toBe('<div><div>Firstbar</div></div>');\n      render(<ParentSecond />, container);\n\n      expect(container.innerHTML).toBe('<div><div>Secondfoo</div></div>');\n    });\n  });\n\n  describe('Inheritance with duplicate render', () => {\n    interface ChildProps {\n      name: string;\n    }\n\n    interface ChildState {\n      data: string;\n    }\n\n    class Child extends Component<ChildProps, ChildState> {\n      public state: ChildState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          data: '',\n        };\n\n        this._update = this._update.bind(this);\n      }\n\n      public _update() {\n        this.setState({\n          data: 'bar',\n        });\n      }\n\n      public componentWillMount() {\n        this.setState({\n          data: 'foo',\n        });\n      }\n\n      public render() {\n        return (\n          <div onclick={this._update}>\n            {this.props.name}\n            {this.state.data}\n          </div>\n        );\n      }\n    }\n\n    class ParentFirst extends Component {\n      protected foo: string;\n\n      constructor(props) {\n        super(props);\n\n        this.foo = 'First';\n      }\n\n      public render() {\n        return (\n          <div>\n            <Child name={this.foo} />\n          </div>\n        );\n      }\n    }\n\n    class ParentSecond extends Component {\n      protected foo: string;\n\n      constructor(props) {\n        super(props);\n\n        this.foo = 'Second';\n      }\n\n      public render() {\n        return (\n          <div>\n            <Child name={this.foo} />\n          </div>\n        );\n      }\n    }\n\n    // For some reason this one breaks but if components are imported separately, it works\n    it('Should not reuse children if parent changes #2', () => {\n      render(<ParentFirst />, container);\n      expect(container.innerHTML).toBe('<div><div>Firstfoo</div></div>');\n      container.firstChild.firstChild.click();\n      expect(container.innerHTML).toBe('<div><div>Firstbar</div></div>');\n      render(<ParentSecond />, container);\n      expect(container.innerHTML).toBe('<div><div>Secondfoo</div></div>');\n    });\n  });\n\n  describe('Inheritance with 1 component per file Common BASE', () => {\n    it('Should not reuse children if parent changes #3', () => {\n      render(<ParentFirstCommon />, container);\n      expect(container.innerHTML).toBe('<div><div>Firstfoo</div></div>');\n      container.firstChild.firstChild.click();\n      expect(container.innerHTML).toBe('<div><div>Firstbar</div></div>');\n      render(<ParentSecondCommon />, container);\n      expect(container.innerHTML).toBe('<div><div>Secondfoo</div></div>');\n    });\n  });\n\n  describe('should handle defaultProps and keys being pass into components', () => {\n    interface CompProps {\n      foo: string;\n    }\n    class Comp extends Component<CompProps> {\n      public render() {\n        return this.props.foo;\n      }\n\n      public static defaultProps = {\n        foo: 'bar',\n      };\n    }\n\n    it('should render the component with a key', () => {\n      let val: string | number = '1';\n\n      render(<Comp key={val} />, container);\n      expect(container.innerHTML).toBe('bar');\n      val = 2;\n      render(<Comp key={val} />, container);\n      expect(container.innerHTML).toBe('bar');\n    });\n  });\n\n  describe('Force update', () => {\n    it('Should not call shouldComponentUpdate', () => {\n      let test = false;\n      let called = false;\n      let doForce;\n\n      class FooBar extends Component {\n        constructor(props) {\n          super(props);\n\n          doForce = this.doForceUpdate.bind(this);\n        }\n\n        public shouldComponentUpdate() {\n          test = true;\n\n          return false;\n        }\n\n        public doForceUpdate() {\n          called = true;\n          this.forceUpdate();\n        }\n\n        public render() {\n          return <div>1</div>;\n        }\n      }\n\n      render(<FooBar />, container);\n\n      expect(container.innerHTML).toEqual('<div>1</div>');\n      expect(test).toEqual(false);\n      expect(called).toEqual(false);\n\n      doForce();\n\n      expect(test).toEqual(false);\n      expect(called).toEqual(true);\n      expect(container.innerHTML).toEqual('<div>1</div>');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/createref.spec.tsx",
    "content": "import {\n  Component,\n  createRef,\n  type InfernoNode,\n  type RefObject,\n  render,\n  rerender,\n} from 'inferno';\n\ndescribe('createRef', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should add DOM reference to \"current\" of ref', () => {\n    let instanceTesting: Testing | null = null;\n\n    class Testing extends Component {\n      public render(): number {\n        instanceTesting = this;\n        return 1;\n      }\n    }\n\n    function Functional(): string {\n      return 'foobar';\n    }\n\n    class Foobar extends Component {\n      private readonly element: RefObject<HTMLSpanElement>;\n      private readonly es6: RefObject<Testing>;\n      private readonly functional: RefObject<unknown>;\n\n      constructor(props) {\n        super(props);\n\n        this.element = createRef();\n        this.es6 = createRef();\n        this.functional = createRef();\n      }\n\n      public componentWillMount(): void {\n        expect(this.element.current).toBe(null);\n        expect(this.es6.current).toBe(null);\n        expect(this.functional.current).toBe(null);\n      }\n\n      public componentDidMount(): void {\n        expect(this.element.current).toBe(container.querySelector('#span'));\n        expect(this.es6.current).toBe(instanceTesting);\n        expect(this.functional.current).toBe(null);\n      }\n\n      public render(): InfernoNode {\n        return (\n          <div>\n            <span id=\"span\" ref={this.element}>\n              Ok\n            </span>\n            <Testing ref={this.es6} />\n            {/* @ts-expect-error ref is not valid for functional component */}\n            <Functional ref={this.functional} />\n          </div>\n        );\n      }\n    }\n\n    render(<Foobar />, container);\n    rerender();\n  });\n\n  it('Should update callback ref for Components too', () => {\n    let instanceTesting: Testing | null = null;\n\n    class Testing extends Component {\n      public render(): number {\n        instanceTesting = this;\n        return 1;\n      }\n    }\n\n    let oldCounter = 0;\n    let oldValue = null;\n    let newCounter = 0;\n    let newValue = null;\n\n    interface FoobarProps {\n      swap?: boolean;\n    }\n\n    class Foobar extends Component<FoobarProps> {\n      private readonly es6Old: (arg) => void;\n      private readonly es6new: (arg) => void;\n\n      constructor(props) {\n        super(props);\n\n        this.es6Old = function (arg) {\n          oldCounter++;\n          oldValue = arg;\n        };\n        this.es6new = function (arg) {\n          newCounter++;\n          newValue = arg;\n        };\n      }\n\n      public render(props): InfernoNode {\n        return (\n          <div>\n            <Testing ref={props.swap ? this.es6Old : this.es6new} />\n          </div>\n        );\n      }\n    }\n\n    render(<Foobar swap={true} />, container);\n\n    expect(oldCounter).toBe(1);\n    expect(oldValue).toBe(instanceTesting);\n    expect(newCounter).toBe(0);\n    expect(newValue).toBe(null);\n\n    render(<Foobar swap={false} />, container);\n\n    expect(oldCounter).toBe(2);\n    expect(oldValue).toBe(null);\n    expect(newCounter).toBe(1);\n    expect(newValue).toBe(instanceTesting);\n  });\n\n  it('Should update callback ref for element vNodes too', () => {\n    let oldCounter = 0;\n    let oldValue = null;\n    let newCounter = 0;\n    let newValue = null;\n\n    interface FoobarProps {\n      swap?: boolean;\n    }\n\n    class Foobar extends Component<FoobarProps> {\n      private readonly es6Old: (arg) => void;\n      private readonly es6new: (arg) => void;\n\n      constructor(props) {\n        super(props);\n\n        this.es6Old = function (arg) {\n          oldCounter++;\n          oldValue = arg;\n        };\n        this.es6new = function (arg) {\n          newCounter++;\n          newValue = arg;\n        };\n      }\n\n      public render(props): InfernoNode {\n        return (\n          <div>\n            <div id={'divi'} ref={props.swap ? this.es6Old : this.es6new} />\n          </div>\n        );\n      }\n    }\n\n    render(<Foobar swap={true} />, container);\n\n    const instanceTesting = container.querySelector('#divi');\n\n    expect(oldCounter).toBe(1);\n    expect(oldValue).toBe(instanceTesting);\n    expect(newCounter).toBe(0);\n    expect(newValue).toBe(null);\n\n    render(<Foobar swap={false} />, container);\n\n    expect(oldCounter).toBe(2);\n    expect(oldValue).toBe(null);\n    expect(newCounter).toBe(1);\n    expect(newValue).toBe(instanceTesting);\n  });\n\n  it('Should update refs and unmount them', () => {\n    let instance: Foobar | null = null;\n\n    let instanceTesting: Testing | null = null;\n\n    class Testing extends Component {\n      public render(): number {\n        instanceTesting = this;\n        return 1;\n      }\n    }\n\n    function Functional(): string {\n      return 'foobar';\n    }\n\n    interface FoobarState {\n      swap: boolean;\n    }\n\n    class Foobar extends Component<any, FoobarState> {\n      public readonly elementOld: RefObject<HTMLSpanElement>;\n      public readonly elementNew: RefObject<HTMLSpanElement>;\n      public readonly es6Old: RefObject<Testing>;\n      public readonly es6new: RefObject<Testing>;\n      public readonly functionalOLD: RefObject<unknown>;\n      public readonly functionalNEW: RefObject<unknown>;\n\n      constructor(props) {\n        super(props);\n\n        instance = this;\n\n        this.elementNew = createRef();\n        this.elementOld = createRef();\n        this.es6Old = createRef();\n        this.es6new = createRef();\n        this.functionalOLD = createRef();\n        this.functionalNEW = createRef();\n\n        this.state = {\n          swap: true,\n        };\n      }\n\n      public componentWillMount(): void {\n        expect(this.elementNew.current).toBe(null);\n        expect(this.elementOld.current).toBe(null);\n        expect(this.es6Old.current).toBe(null);\n        expect(this.es6new.current).toBe(null);\n        expect(this.functionalOLD.current).toBe(null);\n        expect(this.functionalNEW.current).toBe(null);\n      }\n\n      public componentDidMount(): void {\n        expect(this.elementNew.current).toBe(null);\n        expect(this.elementOld.current).toBe(container.querySelector('#span'));\n        expect(this.es6Old.current).toBe(instanceTesting);\n        expect(this.es6new.current).toBe(null);\n        expect(this.functionalOLD.current).toBe(null);\n        expect(this.functionalNEW.current).toBe(null);\n\n        this.setState({\n          swap: false,\n        });\n      }\n\n      public render(_props, { swap }): InfernoNode {\n        return (\n          <div>\n            <span id=\"span\" ref={swap ? this.elementOld : this.elementNew}>\n              Ok\n            </span>\n            <Testing ref={swap ? this.es6Old : this.es6new} />\n            {/* @ts-expect-error Functional component ref */}\n            <Functional ref={swap ? this.functionalOLD : this.functionalNEW} />\n          </div>\n        );\n      }\n    }\n\n    render(<Foobar />, container);\n    rerender();\n\n    // Verify ref updated\n    expect(instance!.elementNew.current).toBe(container.querySelector('#span'));\n    expect(instance!.elementOld.current).toBe(null);\n    expect(instance!.es6Old.current).toBe(null);\n    expect(instance!.es6new.current).toBe(instanceTesting);\n    expect(instance!.functionalOLD.current).toBe(null);\n    expect(instance!.functionalNEW.current).toBe(null);\n\n    render(null, container);\n\n    expect(instance!.elementNew.current).toBe(null);\n    expect(instance!.elementOld.current).toBe(null);\n    expect(instance!.es6Old.current).toBe(null);\n    expect(instance!.es6new.current).toBe(null);\n    expect(instance!.functionalOLD.current).toBe(null);\n    expect(instance!.functionalNEW.current).toBe(null);\n  });\n\n  it('Should change ref to the selected element in a list', () => {\n    const TOTAL_CHILDREN = 5;\n    let setSelected;\n\n    interface ParentState {\n      selected: number;\n    }\n\n    class Parent extends Component<unknown, ParentState> {\n      public state: ParentState;\n      private readonly selectedRef: RefObject<HTMLDivElement>;\n\n      constructor() {\n        super();\n        setSelected = this._setSelected = this._setSelected.bind(this);\n\n        this.selectedRef = createRef();\n        this.state = {\n          selected: 1,\n        };\n      }\n\n      public componentDidMount(): void {\n        expect(this.selectedRef.current).toBe(\n          container.querySelector('#child' + this.state.selected),\n        );\n      }\n\n      public componentDidUpdate(): void {\n        expect(this.selectedRef.current).toBe(\n          container.querySelector('#child' + this.state.selected),\n        );\n      }\n\n      public render(): void {\n        const children: InfernoNode[] = [];\n        for (let i = 0; i < TOTAL_CHILDREN; i++) {\n          const selected = this.state.selected === i ? this.selectedRef : null;\n          children.push(<div key={i} id={'child' + i} ref={selected} />);\n        }\n\n        return <div id=\"parent\">{children}</div>;\n      }\n\n      public _setSelected(selected): void {\n        this.setState({\n          selected,\n        });\n      }\n    }\n\n    render(<Parent />, container);\n\n    setSelected(2);\n\n    rerender();\n\n    setSelected(3);\n\n    rerender();\n\n    setSelected(2);\n\n    rerender();\n\n    setSelected(1);\n\n    rerender();\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/data/common-render/child.tsx",
    "content": "import { Component } from 'inferno';\n\ninterface ChildCommonProps {\n  name: string;\n}\n\ninterface ChildCommonState {\n  data: string;\n}\n\nexport class ChildCommon extends Component<ChildCommonProps, ChildCommonState> {\n  public state: ChildCommonState;\n\n  constructor(props) {\n    super(props);\n\n    this.state = {\n      data: '',\n    };\n\n    this._update = this._update.bind(this);\n  }\n\n  public _update() {\n    this.setState({\n      data: 'bar',\n    });\n  }\n\n  public componentWillMount() {\n    this.setState({\n      data: 'foo',\n    });\n  }\n\n  public render() {\n    return (\n      <div onclick={this._update}>\n        {this.props.name}\n        {this.state.data}\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "packages/inferno/__tests__/data/common-render/parentbase.tsx",
    "content": "import { Component } from 'inferno';\nimport { ChildCommon } from './child';\n\nexport class ParentBaseCommon extends Component {\n  protected foo: string;\n\n  public render() {\n    return (\n      <div>\n        <ChildCommon name={this.foo} />\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "packages/inferno/__tests__/data/common-render/parentfirstcommon.tsx",
    "content": "import { ParentBaseCommon } from './parentbase';\n\nexport class ParentFirstCommon extends ParentBaseCommon {\n  constructor(props) {\n    super(props);\n\n    this.foo = 'First';\n  }\n}\n"
  },
  {
    "path": "packages/inferno/__tests__/data/common-render/parentsecondcommon.tsx",
    "content": "import { ParentBaseCommon } from './parentbase';\n\nexport class ParentSecondCommon extends ParentBaseCommon {\n  constructor(props) {\n    super(props);\n\n    this.foo = 'Second';\n  }\n}\n"
  },
  {
    "path": "packages/inferno/__tests__/defaultprops-typings.spec.tsx",
    "content": "import { Component, render } from 'inferno';\n\ndescribe('default prop typings', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  interface MyComponentProps {\n    name: string;\n    value: number;\n  }\n\n  class MyComponent extends Component<MyComponentProps, any> {\n    constructor(props, context) {\n      super(props, context);\n    }\n\n    public static defaultProps = {\n      name: 'custom-component',\n      value: 107,\n    };\n\n    public render() {\n      return null;\n    }\n  }\n\n  it('TSX Should not require properties from default props', () => {\n    render(<MyComponent name=\"new-name\" />, container);\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/error.spec.tsx",
    "content": "import { Component, type InfernoNode, render, rerender } from 'inferno';\n\ndescribe('Error recovery', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should be possible to render again if user land code crashes in CWM', () => {\n    interface CrasherProps {\n      crash: boolean;\n    }\n\n    interface CrasherState {\n      value: number;\n    }\n\n    class Crasher extends Component<CrasherProps, CrasherState> {\n      public state: CrasherState;\n\n      constructor(props, context) {\n        super(props, context);\n\n        this.state = {\n          value: 1,\n        };\n      }\n\n      public componentWillMount() {\n        if (this.props.crash) {\n          throw Error('test');\n        }\n\n        this.setState({\n          value: 2,\n        });\n      }\n\n      public render() {\n        return <div>{this.state.value}</div>;\n      }\n    }\n\n    try {\n      render(<Crasher crash={true} />, container);\n    } catch (ex) {\n      expect(ex.message).toBe('test');\n    }\n\n    render(<Crasher crash={false} />, container);\n    expect(container.firstChild.innerHTML).toBe('2');\n  });\n\n  it('Should be possible to render again if user land code crashes in ComponentWillUnmount', () => {\n    interface CrasherProps {\n      crash: boolean;\n    }\n\n    interface CrasherState {\n      value: number;\n    }\n\n    class Crasher extends Component<CrasherProps, CrasherState> {\n      public state: CrasherState;\n      constructor(props, context) {\n        super(props, context);\n\n        this.state = {\n          value: 1,\n        };\n      }\n\n      public componentWillUnmount() {\n        if (this.props.crash) {\n          throw Error('test');\n        }\n      }\n\n      public render() {\n        return <div>{this.state.value}</div>;\n      }\n    }\n\n    render(<Crasher crash={true} />, container);\n\n    expect(container.firstChild.innerHTML).toBe('1');\n\n    try {\n      render(null, container);\n    } catch (ex) {\n      expect(ex.message).toBe('test');\n    }\n\n    // No change as it crashed\n    expect(container.firstChild.innerHTML).toBe('1');\n\n    // Try update\n    render(<Crasher crash={false} />, container);\n\n    expect(container.firstChild.innerHTML).toBe('1');\n\n    // Should not crash now\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  /*\n   * THROW ERROR IN\n   *\n   * last  node - render - willMount, didMount, willUpdate, didUpdate, constructor, cwrp\n   * mid   node - render - willMount, didMount, willUpdate, didUpdate, constructor, cwrp\n   * first node - render - willMount, didMount, willUpdate, didUpdate, constructor, cwrp\n   *\n   * force keyed? force non keyed?\n   */\n\n  describe('Error recovery from user land errors', () => {\n    for (const location of ['last', 'mid', 'first']) {\n      for (const crashLocation of [\n        'render',\n        'constructor',\n        'DidMount',\n        'WillMount',\n        'WillReceiveProps',\n        'shouldUpdate',\n        'WillUpdate',\n        'DidUpdate',\n        'getChildContext',\n      ]) {\n        it(\n          'Should recover from subtree crash in ' +\n            location +\n            ' of children when crash happens in components ' +\n            crashLocation,\n          () => {\n            interface CrasherProps {\n              crash: boolean;\n            }\n\n            interface CrasherState {\n              value: string;\n            }\n\n            class Crasher extends Component<CrasherProps, CrasherState> {\n              public state: CrasherState;\n              constructor(props, context) {\n                super(props, context);\n\n                this.state = {\n                  value: '',\n                };\n\n                if (props.crash && crashLocation === 'constructor') {\n                  throw Error('test');\n                }\n              }\n\n              public componentWillMount() {\n                this.setState({\n                  value: 'mounted',\n                });\n\n                if (this.props.crash && crashLocation === 'WillMount') {\n                  throw Error('test');\n                }\n              }\n\n              public componentWillReceiveProps(props) {\n                if (props.crash && crashLocation === 'WillReceiveProps') {\n                  throw Error('test');\n                }\n              }\n\n              public componentDidMount() {\n                if (this.props.crash && crashLocation === 'DidMount') {\n                  throw Error('test');\n                }\n              }\n\n              public shouldComponentUpdate(props) {\n                if (props.crash && crashLocation === 'shouldUpdate') {\n                  throw Error('test');\n                }\n\n                return false;\n              }\n\n              public componentWillUpdate() {\n                if (this.props.crash && crashLocation === 'WillUpdate') {\n                  throw Error('test');\n                }\n              }\n\n              public componentDidUpdate() {\n                if (this.props.crash && crashLocation === 'DidUpdate') {\n                  throw Error('test');\n                }\n              }\n\n              // Unmount hook is still an issue\n              // componentWillUnmount() {\n              //     if (this.props.crash && crashLocation === 'WillUnmount') {\n              //         throw Error('test');\n              //     }\n              // }\n\n              public getChildContext() {\n                if (this.props.crash && crashLocation === 'getChildContext') {\n                  throw Error('test');\n                }\n\n                return {};\n              }\n\n              public render() {\n                if (this.props.crash && crashLocation === 'render') {\n                  throw Error('test');\n                }\n\n                return <div>{this.state.value}</div>;\n              }\n            }\n\n            function TreeOfCrashers({\n              suffle,\n              crash,\n            }: {\n              suffle?: boolean;\n              crash: boolean;\n            }) {\n              const arr: InfernoNode[] = [];\n\n              if (location === 'first') {\n                arr.push(<Crasher crash={crash} />);\n              }\n\n              if (suffle) {\n                arr.push(<span>1</span>);\n                if (location === 'mid') {\n                  arr.push(<Crasher crash={crash} />);\n                }\n                arr.push(<Crasher crash={false} />);\n              } else {\n                if (location === 'mid') {\n                  arr.push(<Crasher crash={crash} />);\n                }\n                arr.push(<Crasher crash={false} />);\n              }\n\n              if (location === 'last') {\n                arr.push(<Crasher crash={crash} />);\n              }\n\n              return <div>{arr}</div>;\n            }\n\n            render(<TreeOfCrashers crash={false} />, container);\n\n            try {\n              render(<TreeOfCrashers suffle={true} crash={true} />, container);\n            } catch (ex) {\n              // do nothing\n            }\n\n            render(<TreeOfCrashers crash={false} />, container);\n\n            expect(container.firstChild.innerHTML).toBe(\n              '<div>mounted</div><div>mounted</div>',\n            );\n          },\n        );\n      }\n    }\n\n    for (const location of ['last', 'mid', 'first']) {\n      for (const crashLocation of [\n        'render',\n        'constructor',\n        'DidMount',\n        'WillMount',\n        'WillReceiveProps',\n        'shouldUpdate',\n        'WillUpdate',\n        'DidUpdate',\n        'getChildContext',\n      ]) {\n        it(\n          'Should recover from subtree crash in NON-KEYED ' +\n            location +\n            ' of children when crash happens in components ' +\n            crashLocation,\n          () => {\n            interface CrasherProps {\n              crash: boolean;\n            }\n\n            interface CrasherState {\n              value: string;\n            }\n\n            class Crasher extends Component<CrasherProps, CrasherState> {\n              public state: CrasherState;\n              constructor(props, context) {\n                super(props, context);\n\n                this.state = {\n                  value: '',\n                };\n\n                if (props.crash && crashLocation === 'constructor') {\n                  throw Error('test');\n                }\n              }\n\n              public componentWillMount() {\n                this.setState({\n                  value: 'mounted',\n                });\n\n                if (this.props.crash && crashLocation === 'WillMount') {\n                  throw Error('test');\n                }\n              }\n\n              public componentWillReceiveProps(props) {\n                if (props.crash && crashLocation === 'WillReceiveProps') {\n                  throw Error('test');\n                }\n              }\n\n              public componentDidMount() {\n                if (this.props.crash && crashLocation === 'DidMount') {\n                  throw Error('test');\n                }\n              }\n\n              public shouldComponentUpdate(props) {\n                if (props.crash && crashLocation === 'shouldUpdate') {\n                  throw Error('test');\n                }\n\n                return false;\n              }\n\n              public componentWillUpdate() {\n                if (this.props.crash && crashLocation === 'WillUpdate') {\n                  throw Error('test');\n                }\n              }\n\n              public componentDidUpdate() {\n                if (this.props.crash && crashLocation === 'DidUpdate') {\n                  throw Error('test');\n                }\n              }\n\n              // Unmount hook is still an issue\n              // componentWillUnmount() {\n              //     if (this.props.crash && crashLocation === 'WillUnmount') {\n              //         throw Error('test');\n              //     }\n              // }\n\n              public getChildContext() {\n                if (this.props.crash && crashLocation === 'getChildContext') {\n                  throw Error('test');\n                }\n\n                return {};\n              }\n\n              public render() {\n                if (this.props.crash && crashLocation === 'render') {\n                  throw Error('test');\n                }\n\n                return <div>{this.state.value}</div>;\n              }\n            }\n\n            function TreeOfCrashers({\n              suffle,\n              crash,\n            }: {\n              suffle?: boolean;\n              crash: boolean;\n            }) {\n              const arr: InfernoNode[] = [];\n\n              if (location === 'first') {\n                arr.push(<Crasher crash={crash} />);\n              }\n\n              if (suffle) {\n                arr.push(<span>1</span>);\n                if (location === 'mid') {\n                  arr.push(<Crasher crash={crash} />);\n                }\n                arr.push(<Crasher crash={false} />);\n              } else {\n                if (location === 'mid') {\n                  arr.push(<Crasher crash={crash} />);\n                }\n                arr.push(<Crasher crash={false} />);\n              }\n\n              if (location === 'last') {\n                arr.push(<Crasher crash={crash} />);\n              }\n\n              return <div $HasNonKeyedChildren>{arr}</div>;\n            }\n\n            render(<TreeOfCrashers crash={false} />, container);\n\n            try {\n              render(<TreeOfCrashers suffle={true} crash={true} />, container);\n            } catch (ex) {\n              // do nothing\n            }\n\n            render(<TreeOfCrashers crash={false} />, container);\n\n            expect(container.firstChild.innerHTML).toBe(\n              '<div>mounted</div><div>mounted</div>',\n            );\n          },\n        );\n      }\n    }\n\n    for (const location of ['last', 'mid', 'first']) {\n      for (const crashLocation of [\n        'render',\n        'constructor',\n        'DidMount',\n        'WillMount',\n        'WillReceiveProps',\n        'shouldUpdate',\n        'WillUpdate',\n        'DidUpdate',\n        'getChildContext',\n      ]) {\n        it(\n          'Should recover from subtree crash in NON-KEYED ' +\n            location +\n            ' of children when crash happens in components ' +\n            crashLocation,\n          () => {\n            interface CrasherProps {\n              crash: boolean;\n            }\n\n            interface CrasherState {\n              value: string;\n            }\n\n            class Crasher extends Component<CrasherProps, CrasherState> {\n              public state: CrasherState;\n              constructor(props, context) {\n                super(props, context);\n\n                this.state = {\n                  value: '',\n                };\n\n                if (props.crash && crashLocation === 'constructor') {\n                  throw Error('test');\n                }\n              }\n\n              public componentWillMount() {\n                this.setState({\n                  value: 'mounted',\n                });\n\n                if (this.props.crash && crashLocation === 'WillMount') {\n                  throw Error('test');\n                }\n              }\n\n              public componentWillReceiveProps(props) {\n                if (props.crash && crashLocation === 'WillReceiveProps') {\n                  throw Error('test');\n                }\n              }\n\n              public componentDidMount() {\n                if (this.props.crash && crashLocation === 'DidMount') {\n                  throw Error('test');\n                }\n              }\n\n              public shouldComponentUpdate(props) {\n                if (props.crash && crashLocation === 'shouldUpdate') {\n                  throw Error('test');\n                }\n\n                return false;\n              }\n\n              public componentWillUpdate() {\n                if (this.props.crash && crashLocation === 'WillUpdate') {\n                  throw Error('test');\n                }\n              }\n\n              public componentDidUpdate() {\n                if (this.props.crash && crashLocation === 'DidUpdate') {\n                  throw Error('test');\n                }\n              }\n\n              // Unmount hook is still an issue\n              // componentWillUnmount() {\n              //     if (this.props.crash && crashLocation === 'WillUnmount') {\n              //         throw Error('test');\n              //     }\n              // }\n\n              public getChildContext() {\n                if (this.props.crash && crashLocation === 'getChildContext') {\n                  throw Error('test');\n                }\n\n                return {};\n              }\n\n              public render() {\n                if (this.props.crash && crashLocation === 'render') {\n                  throw Error('test');\n                }\n\n                return <div>{this.state.value}</div>;\n              }\n            }\n\n            function TreeOfCrashers({\n              suffle,\n              crash,\n            }: {\n              suffle?: boolean;\n              crash: boolean;\n            }) {\n              const arr: InfernoNode[] = [];\n\n              if (location === 'first') {\n                arr.push(<Crasher key=\"first\" crash={crash} />);\n              }\n\n              if (suffle) {\n                arr.push(<span key=\"span\">1</span>);\n                if (location === 'mid') {\n                  arr.push(<Crasher key=\"mid\" crash={crash} />);\n                }\n                arr.push(<Crasher key=\"false-suffle\" crash={false} />);\n              } else {\n                if (location === 'mid') {\n                  arr.push(<Crasher key=\"mid\" crash={crash} />);\n                }\n                arr.push(<Crasher key=\"true-suffle\" crash={false} />);\n              }\n\n              if (location === 'last') {\n                arr.push(<Crasher key=\"last\" crash={crash} />);\n              }\n\n              return <div $HasKeyedChildren>{arr}</div>;\n            }\n\n            render(<TreeOfCrashers crash={false} />, container);\n\n            try {\n              render(<TreeOfCrashers suffle={true} crash={true} />, container);\n            } catch (ex) {\n              // do nothing\n            }\n\n            render(<TreeOfCrashers crash={false} />, container);\n\n            expect(container.firstChild.innerHTML).toBe(\n              '<div>mounted</div><div>mounted</div>',\n            );\n          },\n        );\n      }\n    }\n\n    describe('Error in child component', () => {\n      it('Should not block future updates', (done) => {\n        let childCrasherInstance: ChildCrasher | null = null;\n\n        class BadComponent extends Component {\n          constructor(props) {\n            super(props);\n          }\n\n          public componentWillMount() {\n            throw new Error('Oops!');\n          }\n\n          public render() {\n            return 1;\n          }\n        }\n\n        interface ChildCrasherState {\n          fail: boolean;\n        }\n\n        class ChildCrasher extends Component<unknown, ChildCrasherState> {\n          public state: ChildCrasherState;\n\n          constructor(props) {\n            super(props);\n\n            this.state = {\n              fail: false,\n            };\n\n            childCrasherInstance = this; // For the sake of test\n          }\n\n          public render() {\n            if (!this.state.fail) {\n              return null;\n            }\n\n            return <BadComponent />;\n          }\n        }\n\n        class Parent extends Component {\n          public render() {\n            return (\n              <div>\n                <ChildCrasher />\n              </div>\n            );\n          }\n        }\n\n        render(<Parent />, container);\n\n        expect(container.innerHTML).toBe('<div></div>');\n\n        expect(() => {\n          childCrasherInstance!.setState({\n            fail: true,\n          });\n          rerender();\n        }).toThrow(new Error('Oops!'));\n\n        // Recover from it\n        childCrasherInstance!.setState({\n          fail: false,\n        });\n\n        setTimeout(function () {\n          expect(container.innerHTML).toBe('<div></div>');\n          done();\n        }, 10);\n      });\n\n      it('Should not block future updates - variation 2', () => {\n        let parentInstance: Parent | null = null;\n\n        class BadComponent extends Component {\n          constructor(props) {\n            super(props);\n\n            throw new Error('Oops!');\n          }\n\n          public render() {\n            return <div>Ok</div>;\n          }\n        }\n\n        interface ChildCrasherProps {\n          fail?: boolean;\n        }\n\n        class ChildCrasher extends Component<ChildCrasherProps> {\n          public render() {\n            if (!this.props.fail) {\n              return null;\n            }\n\n            return (\n              <div>\n                <span>1</span>\n                <BadComponent />\n              </div>\n            );\n          }\n        }\n\n        interface ParentProps {\n          fail: boolean;\n        }\n\n        interface ParentState {\n          nodes: boolean;\n        }\n\n        class Parent extends Component<ParentProps, ParentState> {\n          public state: ParentState;\n\n          constructor(props) {\n            super(props);\n\n            this.state = {\n              nodes: false,\n            };\n\n            parentInstance = this; // For the sake of test\n          }\n\n          public render() {\n            return (\n              <div>\n                <span>1</span>\n                {null}\n                <ChildCrasher fail={this.props.fail} />\n              </div>\n            );\n          }\n        }\n\n        expect(() => {\n          render(<Parent fail={true} />, container);\n        }).toThrow(new Error('Oops!'));\n\n        expect(() => {\n          render(<Parent fail={true} />, container);\n        }).toThrow(new Error('Oops!'));\n\n        parentInstance!.setState({\n          nodes: true,\n        });\n        rerender();\n\n        expect(container.innerHTML).toEqual('');\n\n        render(<Parent fail={false} />, container);\n\n        expect(() => {\n          render(<Parent fail={true} />, container);\n        }).toThrow(new Error('Oops!'));\n\n        expect(() => {\n          parentInstance!.setState({\n            nodes: false,\n          });\n          rerender();\n        }).toThrow(new Error('Oops!'));\n\n        expect(() => {\n          parentInstance!.setState({\n            nodes: true,\n          });\n          rerender();\n        }).toThrow(new Error('Oops!'));\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/forceUpdate.spec.tsx",
    "content": "import { Component, render, rerender } from 'inferno';\n\ndescribe('forceUpdate', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    rerender(); // Flush pending stuff, if any\n    render(null, container);\n    document.body.removeChild(container);\n    container.innerHTML = '';\n  });\n\n  // https://jsfiddle.net/pnwLh7au/\n  it('Should have new state in render when changed state during setState + forceUpdate inside lifecycle methods and render only once', () => {\n    let updated = 0;\n\n    class Parent extends Component {\n      public render() {\n        return (\n          <div>\n            <Child />\n          </div>\n        );\n      }\n    }\n\n    class Child extends Component {\n      public state = {\n        foo: 'bar',\n      };\n\n      public componentDidMount() {\n        this.setState({\n          foo: 'bar2',\n        });\n        this.forceUpdate();\n      }\n\n      public componentDidUpdate() {\n        updated++;\n      }\n\n      public render() {\n        return <div>{this.state.foo}</div>;\n      }\n    }\n\n    render(<Parent />, container);\n    expect(container.firstChild.firstChild.innerHTML).toBe('bar');\n\n    rerender();\n\n    expect(container.firstChild.firstChild.innerHTML).toBe('bar2');\n    expect(updated).toBe(1);\n  });\n\n  it('Should ignore shouldComponentUpdate when forceUpdate called like React does', () => {\n    let updated = 0;\n\n    class Parent extends Component {\n      public render() {\n        return (\n          <div>\n            <Child />\n          </div>\n        );\n      }\n    }\n\n    class Child extends Component {\n      public state = {\n        foo: 'bar',\n      };\n\n      public shouldComponentUpdate(_prevProps, prevState) {\n        return prevState.foo !== this.state.foo;\n      }\n\n      public componentDidMount() {\n        this.forceUpdate();\n      }\n\n      public render() {\n        updated++;\n        return <div>{this.state.foo}</div>;\n      }\n    }\n\n    render(<Parent />, container);\n    expect(container.firstChild.firstChild.innerHTML).toBe('bar');\n    expect(updated).toBe(1);\n\n    rerender();\n\n    expect(container.firstChild.firstChild.innerHTML).toBe('bar');\n    expect(updated).toBe(2);\n  });\n\n  // As per React https://jsfiddle.net/pnwLh7au/\n  // React has a different flow when setState is called outside lifecycle methods or event handlers (https://jsfiddle.net/egd1kuz6/),\n  // but inferno has another flow for setState and Inferno.\n  // Inferno collapses several `setState` even if they are called outside event listeners or lifecycle methods. So forceUpdate follows it\n  it('Should use the updated state when forceUpdate called like React does even if shouldComponentUpdate ignores it', () => {\n    let updated = 0;\n\n    class Parent extends Component {\n      public render() {\n        return (\n          <div>\n            <Child />\n          </div>\n        );\n      }\n    }\n\n    class Child extends Component {\n      public state = {\n        foo: 'bar',\n      };\n\n      public shouldComponentUpdate() {\n        return false;\n      }\n\n      public componentDidMount() {\n        this.setState({ foo: 'bar2' });\n        this.forceUpdate();\n      }\n\n      public render() {\n        updated++;\n        return <div>{this.state.foo}</div>;\n      }\n    }\n\n    render(<Parent />, container);\n    expect(container.firstChild.firstChild.innerHTML).toBe('bar');\n    expect(updated).toBe(1);\n\n    rerender();\n\n    expect(container.firstChild.firstChild.innerHTML).toBe('bar2');\n    expect(updated).toBe(2);\n  });\n\n  // As per React https://jsfiddle.net/pnwLh7au/\n  it('Should use the updated state when forceUpdate called before setState like React does even if shouldComponentUpdate ignores it', () => {\n    let updated = 0;\n\n    class Parent extends Component {\n      public render() {\n        return (\n          <div>\n            <Child />\n          </div>\n        );\n      }\n    }\n\n    class Child extends Component {\n      public state = {\n        foo: 'bar',\n      };\n\n      public shouldComponentUpdate() {\n        return false;\n      }\n\n      public componentDidMount() {\n        this.forceUpdate();\n        this.setState({ foo: 'bar2' });\n      }\n\n      public render() {\n        updated++;\n        return <div>{this.state.foo}</div>;\n      }\n    }\n\n    render(<Parent />, container);\n    expect(container.firstChild.firstChild.innerHTML).toBe('bar');\n    expect(updated).toBe(1);\n\n    rerender();\n\n    expect(container.firstChild.firstChild.innerHTML).toBe('bar2');\n    expect(updated).toBe(2);\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/formelements.spec.tsx",
    "content": "import { Component, linkEvent, render } from 'inferno';\n\ndescribe('FormElements', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('text input', () => {\n    interface TextBoxProps {\n      value: string | number;\n    }\n    class TextBox extends Component<TextBoxProps> {\n      constructor(props) {\n        super(props);\n      }\n\n      public render() {\n        return (\n          <div>\n            <input type=\"text\" value={this.props.value} />\n          </div>\n        );\n      }\n    }\n\n    it('Should set value as text on render', () => {\n      render(<TextBox value={1} />, container);\n      expect(container.querySelector('input').value).toBe('1');\n    });\n\n    it('Should override changed value on next render', () => {\n      render(<TextBox value={1} />, container);\n      let input = container.querySelector('input');\n      expect(input.value).toBe('1');\n      input.value = '2'; // Simulate user typing '2'\n      expect(input.value).toBe('2');\n      render(<TextBox value={3} />, container);\n      input = container.querySelector('input');\n      expect(input.value).toBe('3');\n    });\n\n    it('Should override changed value on next render even when value is same as on prev render', () => {\n      render(<TextBox value={1} />, container);\n      let input = container.querySelector('input');\n      expect(input.value).toBe('1');\n      input.value = '2'; // Simulate user typing '2'\n      expect(input.value).toBe('2');\n      render(<TextBox value={1} />, container);\n      input = container.querySelector('input');\n      expect(input.value).toBe('1');\n    });\n\n    it('Controlled - oninput - Should have updated props in onInput callbacks', () => {\n      interface ExampleProps {\n        value: number;\n        callback: (value: number) => void;\n      }\n\n      class Example extends Component<ExampleProps> {\n        constructor(props, context) {\n          super(props, context);\n\n          this._method = this._method.bind(this);\n        }\n\n        public _method() {\n          this.props.callback(this.props.value);\n        }\n\n        public render() {\n          return <input type=\"text\" onInput={this._method} value=\"test\" />;\n        }\n      }\n      const spy = jasmine.createSpy('spy');\n\n      render(<Example callback={spy} value={1} />, container);\n\n      let event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(spy).toHaveBeenCalledTimes(1);\n      expect(spy.calls.argsFor(0)[0]).toBe(1); // Verify initial props are correct\n\n      // Then update component\n      render(<Example callback={spy} value={2} />, container);\n\n      event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(spy).toHaveBeenCalledTimes(2);\n      expect(spy.calls.argsFor(1)[0]).toBe(2); // Verify props have changed\n    });\n\n    it('Controlled - onInput - Should have updated props in onInput callbacks', () => {\n      interface ExampleProps {\n        value: number;\n        callback: (value: number) => void;\n      }\n\n      class Example extends Component<ExampleProps> {\n        constructor(props, context) {\n          super(props, context);\n\n          this._method = this._method.bind(this);\n        }\n\n        public _method() {\n          this.props.callback(this.props.value);\n        }\n\n        public render() {\n          return <input type=\"text\" onInput={this._method} value=\"test\" />;\n        }\n      }\n\n      let callCounter = 0;\n      const args: number[] = [];\n\n      const spy = function (arg) {\n        callCounter++;\n        args.push(arg);\n      };\n\n      render(<Example callback={spy} value={1} />, container);\n\n      let event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(callCounter).toBe(1);\n      expect(args[0]).toBe(1);\n\n      // Then update component\n      render(<Example callback={spy} value={2} />, container);\n\n      event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(callCounter).toBe(2);\n      expect(args[1]).toBe(2);\n    });\n\n    it('Controlled - onInput - Should have updated props in onInput callbacks in setState callback', () => {\n      interface ExampleProps {\n        value: number;\n        callback: (value: number, a: number) => void;\n      }\n\n      interface ExampleState {\n        a: number;\n      }\n\n      class Example extends Component<ExampleProps, ExampleState> {\n        public state: ExampleState;\n\n        constructor(props, context) {\n          super(props, context);\n\n          this.state = {\n            a: 0,\n          };\n\n          this._method = this._method.bind(this);\n        }\n\n        public test() {\n          this.props.callback(this.props.value, this.state.a);\n        }\n\n        public _method() {\n          this.setState(\n            {\n              a: this.props.value,\n            },\n            this.test,\n          );\n        }\n\n        public render() {\n          return <input type=\"text\" onInput={this._method} value=\"test\" />;\n        }\n      }\n\n      const spy = jasmine.createSpy('spy');\n\n      render(<Example callback={spy} value={1} />, container);\n\n      let event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(spy).toHaveBeenCalledTimes(1);\n      expect(spy.calls.argsFor(0)[0]).toBe(1); // Verify initial props are correct\n\n      // Then update component\n      render(<Example callback={spy} value={2} />, container);\n\n      event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(spy).toHaveBeenCalledTimes(2);\n      expect(spy.calls.argsFor(1)[0]).toBe(2); // Verify props have changed\n    });\n\n    it('Controlled - onInput (linkEvent) - Should have updated props in onInput callbacks', () => {\n      interface ExampleProps {\n        value: number;\n        callback: (value: number, a: number) => void;\n      }\n\n      class Example extends Component<ExampleProps> {\n        constructor(props, context) {\n          super(props, context);\n        }\n\n        public static _method(me) {\n          me.props.callback(me.props.value);\n        }\n\n        public render() {\n          return (\n            <input\n              type=\"text\"\n              onInput={linkEvent(this, Example._method)}\n              value=\"test\"\n            />\n          );\n        }\n      }\n\n      const spy = jasmine.createSpy('spy');\n\n      render(<Example callback={spy} value={1} />, container);\n\n      let event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(spy).toHaveBeenCalledTimes(1);\n      expect(spy.calls.argsFor(0)[0]).toBe(1); // Verify initial props are correct\n\n      // Then update component\n      render(<Example callback={spy} value={2} />, container);\n\n      event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(spy).toHaveBeenCalledTimes(2);\n      expect(spy.calls.argsFor(1)[0]).toBe(2); // Verify props have changed\n    });\n\n    it('NON Controlled - onInput (linkEvent) - Should have updated props in onInput callbacks', () => {\n      interface ExampleProps {\n        value: number;\n        callback: (value: number, a: number) => void;\n      }\n\n      class Example extends Component<ExampleProps> {\n        constructor(props, context) {\n          super(props, context);\n        }\n\n        public static _method(me) {\n          me.props.callback(me.props.value);\n        }\n\n        public render() {\n          return (\n            <input type=\"text\" onInput={linkEvent(this, Example._method)} />\n          );\n        }\n      }\n\n      const spy = jasmine.createSpy('spy');\n\n      render(<Example callback={spy} value={1} />, container);\n\n      let event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(spy).toHaveBeenCalledTimes(1);\n      expect(spy.calls.argsFor(0)[0]).toBe(1); // Verify initial props are correct\n\n      // Then update component\n      render(<Example callback={spy} value={2} />, container);\n\n      event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(spy).toHaveBeenCalledTimes(2);\n      expect(spy.calls.argsFor(1)[0]).toBe(2); // Verify props have changed\n    });\n\n    it('NON Controlled - onInput - Should have updated props in onInput callbacks', () => {\n      interface ExampleProps {\n        value: number;\n        callback: (value: number) => void;\n      }\n\n      class Example extends Component<ExampleProps> {\n        constructor(props, context) {\n          super(props, context);\n\n          this._method = this._method.bind(this);\n        }\n\n        public _method() {\n          this.props.callback(this.props.value);\n        }\n\n        public render() {\n          return <input type=\"text\" onInput={this._method} />;\n        }\n      }\n\n      const spy = jasmine.createSpy('spy');\n\n      render(<Example callback={spy} value={1} />, container);\n\n      let event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(spy).toHaveBeenCalledTimes(1);\n      expect(spy.calls.argsFor(0)[0]).toBe(1); // Verify initial props are correct\n\n      // Then update component\n      render(<Example callback={spy} value={2} />, container);\n\n      event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n      container.firstChild.dispatchEvent(event);\n\n      expect(spy).toHaveBeenCalledTimes(2);\n      expect(spy.calls.argsFor(1)[0]).toBe(2); // Verify props have changed\n    });\n  });\n\n  describe('input type checkbox', () => {\n    interface CheckBoxProps {\n      checked?: boolean;\n    }\n\n    class CheckBox extends Component<CheckBoxProps> {\n      constructor(props) {\n        super(props);\n      }\n\n      public render() {\n        return (\n          <div>\n            <input type=\"checkbox\" checked={this.props.checked} />\n          </div>\n        );\n      }\n    }\n\n    it('Should set checked on render', () => {\n      render(<CheckBox checked={true} />, container);\n      expect(container.querySelector('input').checked).toBe(true);\n    });\n\n    it('Should set checked on render #2', () => {\n      render(<CheckBox checked={false} />, container);\n      expect(container.querySelector('input').checked).toBe(false);\n    });\n\n    it('Should set checked on render #3', () => {\n      render(<CheckBox />, container);\n      expect(container.querySelector('input').checked).toBe(false);\n    });\n\n    it('Should override changed value on next render', () => {\n      render(<CheckBox checked={false} />, container);\n      let input = container.querySelector('input');\n      expect(input.checked).toBe(false);\n      input.checked = false; // Simulate user clicking checkbox twice\n      render(<CheckBox checked={true} />, container);\n      input = container.querySelector('input');\n      expect(input.checked).toBe(true);\n    });\n\n    it('Should override changed value on next render even when value is same as on prev render', () => {\n      render(<CheckBox checked={false} />, container);\n      let input = container.querySelector('input');\n      expect(input.checked).toBe(false);\n      input.checked = true; // Simulate user clicking checkbox\n      expect(input.checked).toBe(true);\n      render(<CheckBox checked={false} />, container);\n      input = container.querySelector('input');\n      expect(input.checked).toBe(false);\n    });\n\n    it('Should override changed value on next render even when value is same as on prev render #1', () => {\n      render(<CheckBox checked={true} />, container);\n      let input = container.querySelector('input');\n      expect(input.checked).toBe(true);\n      input.checked = false; // Simulate user clicking checkbox\n      expect(input.checked).toBe(false);\n      render(<CheckBox checked={true} />, container);\n      input = container.querySelector('input');\n      expect(input.checked).toBe(true);\n    });\n\n    it('Should support indeterminate state', () => {\n      let input;\n\n      render(\n        <input\n          ref={(dom) => (input = dom)}\n          type=\"checkbox\"\n          checked={false}\n          indeterminate={true}\n        />,\n        container,\n      );\n\n      expect(input.indeterminate).toBe(true);\n      expect(input.checked).toBe(false);\n\n      render(\n        <input\n          ref={(dom) => (input = dom)}\n          type=\"checkbox\"\n          checked={false}\n          indeterminate={false}\n        />,\n        container,\n      );\n\n      expect(input.indeterminate).toBe(false);\n      expect(input.checked).toBe(false);\n\n      render(\n        <input\n          ref={(dom) => (input = dom)}\n          type=\"checkbox\"\n          checked={true}\n          indeterminate={false}\n        />,\n        container,\n      );\n\n      expect(input.indeterminate).toBe(false);\n      expect(input.checked).toBe(true);\n    });\n  });\n\n  // https://facebook.github.io/react/docs/forms.html\n  describe('React form spec', () => {\n    describe('Controlled select list', () => {\n      interface SelectListProps {\n        value: string;\n      }\n\n      class SelectList extends Component<SelectListProps> {\n        constructor(props) {\n          super(props);\n        }\n\n        public render() {\n          return (\n            <div>\n              <select value={this.props.value}>\n                <option value=\"A\">A</option>\n                <option value=\"B\">B</option>\n                <option value=\"C\">C</option>\n              </select>\n            </div>\n          );\n        }\n      }\n\n      it('Should pre select option by value', () => {\n        render(<SelectList value=\"B\" />, container);\n        const selectList = container.querySelector('select');\n        expect(selectList.childNodes[0].selected).toBe(false);\n        expect(selectList.childNodes[1].selected).toBe(true);\n        expect(selectList.childNodes[2].selected).toBe(false);\n      });\n\n      it('Should change value based on value property', () => {\n        render(<SelectList value=\"B\" />, container);\n        let selectList = container.querySelector('select');\n        expect(selectList.childNodes[0].selected).toBe(false);\n        expect(selectList.childNodes[1].selected).toBe(true);\n        expect(selectList.childNodes[2].selected).toBe(false);\n\n        render(<SelectList value=\"C\" />, container);\n        selectList = container.querySelector('select');\n        expect(selectList.childNodes[0].selected).toBe(false);\n        expect(selectList.childNodes[1].selected).toBe(false);\n        expect(selectList.childNodes[2].selected).toBe(true);\n      });\n    });\n\n    describe('Controlled select list updates', () => {\n      let updater;\n\n      interface SelectListState {\n        value: string;\n      }\n\n      class SelectList extends Component<unknown, SelectListState> {\n        public state: SelectListState;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            value: 'A',\n          };\n\n          updater = (e) => {\n            this.setState(e);\n          };\n        }\n\n        public buildOptionsDynamically() {\n          return [\n            <option value=\"A\">A</option>,\n            <option value=\"B\">B</option>,\n            <option value=\"C\">C</option>,\n          ];\n        }\n\n        public render() {\n          return (\n            <div>\n              <select value={this.state.value}>\n                {this.buildOptionsDynamically()}\n              </select>\n            </div>\n          );\n        }\n      }\n\n      it('Should pre select option by value on update', (done) => {\n        render(<SelectList />, container);\n        let selectList = container.querySelector('select');\n        expect(selectList.childNodes[0].selected).toBe(true);\n        expect(selectList.childNodes[1].selected).toBe(false);\n        expect(selectList.childNodes[2].selected).toBe(false);\n\n        updater({ value: 'B' });\n        setTimeout(() => {\n          selectList = container.querySelector('select');\n          expect(selectList.childNodes[0].selected).toBe(false);\n          expect(selectList.childNodes[1].selected).toBe(true);\n          expect(selectList.childNodes[2].selected).toBe(false);\n          done();\n        }, 10);\n      });\n    });\n\n    describe('input range scu', () => {\n      it('Should have correct value on initial render', () => {\n        class TestInputRange extends Component {\n          public shouldComponentUpdate() {\n            return false;\n          }\n\n          public render() {\n            return (\n              <input\n                name=\"test\"\n                type=\"range\"\n                min={50}\n                max={500}\n                step={5}\n                defaultValue={260}\n              />\n            );\n          }\n        }\n        render(<TestInputRange />, container);\n\n        expect(container.firstChild.value).toBe('260');\n        expect(container.firstChild.defaultValue).toBe('260');\n      });\n\n      it('Should have defaultValue even when defaultValue is omitted, if value exists', () => {\n        class TestInputRange extends Component {\n          public shouldComponentUpdate() {\n            return false;\n          }\n\n          public render() {\n            return (\n              <input\n                name=\"test\"\n                type=\"range\"\n                min={50}\n                max={500}\n                step={5}\n                value=\"110\"\n              />\n            );\n          }\n        }\n        render(<TestInputRange />, container);\n\n        expect(container.firstChild.value).toBe('110');\n        expect(container.firstChild.defaultValue).toBe('110');\n      });\n    });\n\n    describe('Non-controlled select element', () => {\n      it('Should have 2nd option selected', () => {\n        render(\n          <select>\n            <option value=\"a\">a</option>\n            <option selected={true} value=\"b\">\n              b\n            </option>\n          </select>,\n          container,\n        );\n\n        expect(container.firstChild.children[0].selected).toBe(false);\n        expect(container.firstChild.children[1].selected).toBe(true);\n      });\n\n      it('should render specified default selected option', () => {\n        render(\n          <div>\n            <select>\n              <option value=\"a\">a</option>\n              <option selected={true} value=\"b\">\n                b\n              </option>\n            </select>\n          </div>,\n          container,\n        );\n\n        expect(container.querySelector('select').children[0].selected).toEqual(\n          false,\n        );\n        expect(container.querySelector('select').children[1].selected).toEqual(\n          true,\n        );\n      });\n    });\n\n    describe('callbacks with FormElements', () => {\n      it('Should call latest calback from props', () => {\n        interface CompAState {\n          orderedConfigs: Array<{ value: boolean }>;\n        }\n        class CompA extends Component<unknown, CompAState> {\n          public state: CompAState;\n          constructor(props) {\n            super(props);\n            this.state = {\n              orderedConfigs: [\n                { value: false },\n                { value: true },\n                { value: false },\n              ],\n            };\n          }\n\n          public handleClick(that, { targetConf, targetIndex }) {\n            const newConfigs = that.state.orderedConfigs.map((conf, index) =>\n              index === targetIndex ? { value: !targetConf.value } : conf,\n            );\n\n            this.setState({ orderedConfigs: newConfigs });\n          }\n\n          public render() {\n            return (\n              <CompB\n                orderedConfigs={this.state.orderedConfigs}\n                onClick={(...args) => {\n                  this.handleClick(this, ...args);\n                }}\n              />\n            );\n          }\n        }\n\n        interface CompBProps {\n          orderedConfigs: Array<{ value: boolean }>;\n          onClick: (arg: {\n            targetConf: { value: boolean };\n            targetIndex: number;\n          }) => void;\n        }\n\n        const CompB = function renderCompB(props: CompBProps) {\n          return (\n            <div>\n              {props.orderedConfigs.map((conf, index) => (\n                <input\n                  type=\"checkbox\"\n                  checked={conf.value}\n                  onClick={() => {\n                    props.onClick({ targetConf: conf, targetIndex: index });\n                  }}\n                />\n              ))}\n            </div>\n          );\n        };\n\n        render(<CompA />, container);\n\n        expect(container.firstChild.firstChild.checked).toBe(false);\n        // expect(container.querySelectorAll('input:checked').length).toEqual(1);\n\n        let input = container.querySelector('input');\n        input.click();\n\n        expect(container.firstChild.firstChild.checked).toBe(true);\n        // expect(container.querySelectorAll('input:checked').length).toEqual(2);\n\n        input = container.querySelector('input');\n        input.click();\n\n        expect(container.firstChild.firstChild.checked).toBe(false);\n        // expect(container.querySelectorAll('input:checked').length).toEqual(1);\n      });\n    });\n\n    describe('Controlled inputs, checkbox', () => {\n      it('Should keep unChecked if checked is false', () => {\n        render(\n          <label>\n            <input type=\"checkbox\" checked={false} name=\"test\" value=\"test\" />{' '}\n            test\n          </label>,\n          container,\n        );\n\n        // Verify its not checked\n        const input = container.querySelector('input');\n\n        expect(input.checked).toBe(false);\n\n        input.click();\n\n        expect(input.checked).toBe(false);\n      });\n\n      it('Should be possible to control checkbox by props', () => {\n        interface ComponentTestState {\n          checked: boolean;\n        }\n        class ComponentTest extends Component<unknown, ComponentTestState> {\n          public state: ComponentTestState;\n\n          constructor(props) {\n            super(props);\n            this.state = { checked: false };\n          }\n\n          public handleClick() {\n            this.setState((state) => ({ checked: !state.checked }));\n          }\n\n          public render() {\n            return (\n              <div>\n                <button\n                  onClick={() => {\n                    this.handleClick();\n                  }}\n                />\n                <input type=\"checkbox\" checked={this.state.checked} />\n              </div>\n            );\n          }\n        }\n\n        render(<ComponentTest />, container);\n\n        expect(container.querySelectorAll('input').length).toBe(1);\n\n        const input = container.querySelector('input');\n        const button = container.querySelector('button');\n\n        expect(input.checked).toBe(false);\n\n        button.click();\n\n        expect(input.checked).toBe(true);\n      });\n\n      it('Clicking checkbox should have value changed in callback, and reverted after it (unless no change in state)', () => {\n        let changeToValue = true;\n\n        interface ComponentTestState {\n          checked: boolean;\n        }\n        class ComponentTest extends Component<unknown, ComponentTestState> {\n          public state: ComponentTestState;\n          constructor(props) {\n            super(props);\n            this.state = { checked: true };\n          }\n\n          public handleClick(event) {\n            expect(event.currentTarget.checked).toBe(false);\n\n            this.setState(() => ({ checked: changeToValue }));\n          }\n\n          public render() {\n            return (\n              <div>\n                <input\n                  onClick={(e) => {\n                    this.handleClick(e);\n                  }}\n                  type=\"checkbox\"\n                  checked={this.state.checked}\n                />\n              </div>\n            );\n          }\n        }\n\n        render(<ComponentTest />, container);\n\n        expect(container.querySelectorAll('input').length).toBe(1);\n\n        const input = container.querySelector('input');\n\n        expect(input.checked).toBe(true);\n\n        input.click();\n\n        expect(input.checked).toBe(true);\n\n        changeToValue = false;\n\n        input.click();\n\n        expect(input.checked).toBe(false);\n      });\n\n      /* Same test as above, but in opposite order */\n      it('Clicking checkbox should have value changed in callback, and reverted after it (unless no change in state) #2', () => {\n        let changeToValue = false;\n\n        interface ComponentTestState {\n          checked: boolean;\n        }\n        class ComponentTest extends Component<unknown, ComponentTestState> {\n          public state: ComponentTestState;\n          constructor(props) {\n            super(props);\n            this.state = { checked: false };\n          }\n\n          public handleClick(event) {\n            expect(event.currentTarget.checked).toBe(true);\n\n            this.setState(() => ({ checked: changeToValue }));\n          }\n\n          public render() {\n            return (\n              <div>\n                <input\n                  onClick={(e) => {\n                    this.handleClick(e);\n                  }}\n                  type=\"checkbox\"\n                  checked={this.state.checked}\n                />\n              </div>\n            );\n          }\n        }\n\n        render(<ComponentTest />, container);\n\n        expect(container.querySelectorAll('input').length).toBe(1);\n\n        const input = container.querySelector('input');\n\n        expect(input.checked).toBe(false); // Initially false\n\n        input.click(); // Inside event handler should be true\n\n        expect(input.checked).toBe(false); // After render, it should be false again\n\n        changeToValue = true;\n\n        input.click(); // Inside event handler should be true\n\n        expect(input.checked).toBe(true); // Now it should be true because value was changed in state\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/forward-ref.spec.tsx",
    "content": "import {\n  Component,\n  createRef,\n  forwardRef,\n  type RefObject,\n  render,\n} from 'inferno';\n\ndescribe('Forward Ref', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should be possible to forward createRef', () => {\n    const FancyButton = forwardRef((props, ref) => (\n      <button ref={ref} className=\"FancyButton\">\n        {props.children}\n      </button>\n    ));\n\n    expect(FancyButton.render).toBeDefined();\n\n    class Hello extends Component {\n      private readonly btn: RefObject<Element>;\n\n      constructor(props) {\n        super(props);\n\n        // You can now get a ref directly to the DOM button:\n        this.btn = createRef();\n      }\n\n      public componentDidMount() {\n        expect(this.btn.current).toBe(container.querySelector('button'));\n      }\n\n      public render() {\n        return <FancyButton ref={this.btn}>Click me!</FancyButton>;\n      }\n    }\n\n    render(<Hello />, container);\n\n    expect(container.innerHTML).toBe(\n      '<button class=\"FancyButton\">Click me!</button>',\n    );\n  });\n\n  it('Should be possible to forward callback ref', () => {\n    const FancyButton = forwardRef((props, ref) => (\n      <button ref={ref} className=\"FancyButton\">\n        {props.children}\n      </button>\n    ));\n\n    expect(FancyButton.render).toBeDefined();\n\n    class Hello extends Component {\n      public render() {\n        return (\n          <FancyButton\n            ref={(btn) => {\n              if (btn) {\n                expect(btn).toBe(container.querySelector('button'));\n              }\n            }}\n          >\n            Click me!\n          </FancyButton>\n        );\n      }\n    }\n\n    render(<Hello />, container);\n\n    expect(container.innerHTML).toBe(\n      '<button class=\"FancyButton\">Click me!</button>',\n    );\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be possible to patch forwardRef component', () => {\n    const FancyButton = forwardRef((props, ref) => {\n      return (\n        <button ref={ref} className=\"FancyButton\">\n          {props.children}\n        </button>\n      );\n    });\n\n    expect(FancyButton.render).toBeDefined();\n\n    let firstVal = null;\n\n    render(\n      <FancyButton\n        ref={(btn) => {\n          firstVal = btn;\n        }}\n      >\n        Click me!\n      </FancyButton>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<button class=\"FancyButton\">Click me!</button>',\n    );\n    expect(firstVal).not.toBe(null);\n\n    let secondVal = null;\n\n    render(\n      <FancyButton\n        ref={(btn) => {\n          secondVal = btn;\n        }}\n      >\n        Click me! 222\n      </FancyButton>,\n      container,\n    );\n\n    expect(firstVal).toBe(null);\n    expect(secondVal).not.toBe(null);\n\n    expect(container.innerHTML).toBe(\n      '<button class=\"FancyButton\">Click me! 222</button>',\n    );\n  });\n\n  describe('Validations', () => {\n    it('Should log error if input is: Component, vNode or invalid value', () => {\n      const consoleSpy = spyOn(console, 'error');\n\n      class Foobar extends Component {}\n\n      let i = 0;\n\n      // @ts-expect-error\n      forwardRef(false);\n      expect(consoleSpy.calls.count()).toEqual(++i);\n\n      // @ts-expect-error\n      forwardRef(true);\n      expect(consoleSpy.calls.count()).toEqual(++i);\n\n      // @ts-expect-error\n      forwardRef({});\n      expect(consoleSpy.calls.count()).toEqual(++i);\n\n      // @ts-expect-error\n      forwardRef('asd');\n      expect(consoleSpy.calls.count()).toEqual(++i);\n\n      // @ts-expect-error\n      forwardRef(undefined);\n      expect(consoleSpy.calls.count()).toEqual(++i);\n\n      // @ts-expect-error\n      forwardRef(8);\n      expect(consoleSpy.calls.count()).toEqual(++i);\n\n      // TODO: improve forward ref typings\n      forwardRef(<div>1</div>);\n      expect(consoleSpy.calls.count()).toEqual(++i);\n\n      forwardRef(<Foobar />);\n      expect(consoleSpy.calls.count()).toEqual(++i);\n\n      // This is ok\n      forwardRef(function () {\n        return <div>1</div>;\n      });\n      expect(consoleSpy.calls.count()).toEqual(i);\n    });\n  });\n\n  it('Should be possible to extent forwardRef object', () => {\n    const objRef = createRef();\n    const RefComponent = forwardRef((props, ref) => (\n      <div ref={ref} {...props}>\n        1\n      </div>\n    ));\n\n    RefComponent.staticMember = 'asd';\n\n    render(<RefComponent ref={objRef} />, container);\n\n    expect(container.innerHTML).toBe('<div>1</div>');\n    expect(objRef.current!.outerHTML).toBe('<div>1</div>');\n\n    expect(RefComponent.staticMember).toBe('asd');\n  });\n\n  describe('Inferno specifics', () => {\n    it('Should support defaultProps and defaultHooks', () => {\n      function CoolStuff(props, ref) {\n        return (\n          <div className={props.className}>\n            <span ref={ref}>{props.children}</span>\n            {props.foo}\n          </div>\n        );\n      }\n\n      CoolStuff.defaultProps = {\n        foo: 'bar',\n      };\n      CoolStuff.defaultHooks = {\n        onComponentWillMount() {},\n      };\n\n      const spy = spyOn(CoolStuff.defaultHooks, 'onComponentWillMount');\n\n      const ForwardCom = forwardRef(CoolStuff);\n\n      expect(ForwardCom.render).toBe(CoolStuff);\n\n      class Hello extends Component {\n        public render() {\n          return (\n            <ForwardCom\n              className=\"okay\"\n              ref={(btn) => {\n                if (btn) {\n                  expect(btn).toBe(container.querySelector('span'));\n                }\n              }}\n            >\n              <a>1</a>\n            </ForwardCom>\n          );\n        }\n      }\n\n      render(<Hello />, container);\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"okay\"><span><a>1</a></span>bar</div>',\n      );\n      expect(spy.calls.count()).toBe(1);\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/fragments.spec.tsx",
    "content": "import {\n  Component,\n  createFragment,\n  createPortal,\n  Fragment, InfernoKeyedNode,\n  type InfernoNode,\n  render,\n} from 'inferno';\nimport { ChildFlags } from 'inferno-vnode-flags';\n\ndescribe('Fragments', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should render and unmount fragment', () => {\n    class Example extends Component {\n      public render() {\n        return createFragment(\n          [<div>First</div>, <div>second</div>],\n          ChildFlags.HasNonKeyedChildren,\n        );\n      }\n    }\n\n    render(<Example />, container);\n\n    expect(container.innerHTML).toBe('<div>First</div><div>second</div>');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should render nested fragment', () => {\n    class Example extends Component {\n      public render() {\n        return createFragment(\n          [\n            <div>First</div>,\n            createFragment(\n              [<div>Sub1</div>, <div>Sub2</div>],\n              ChildFlags.HasNonKeyedChildren,\n            ),\n            <div>second</div>,\n          ],\n          ChildFlags.HasNonKeyedChildren,\n        );\n      }\n    }\n\n    render(<Example />, container);\n\n    expect(container.innerHTML).toBe(\n      '<div>First</div><div>Sub1</div><div>Sub2</div><div>second</div>',\n    );\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be to replace component with fragment with another component', () => {\n    class Example extends Component {\n      public render() {\n        return createFragment(\n          [\n            <div>First</div>,\n            createFragment(\n              [<div>Sub1</div>, <div>Sub2</div>],\n              ChildFlags.HasNonKeyedChildren,\n            ),\n            <div>second</div>,\n          ],\n          ChildFlags.HasNonKeyedChildren,\n        );\n      }\n    }\n\n    function FunctionalComp() {\n      return createFragment(\n        [<div>Functional</div>],\n        ChildFlags.HasNonKeyedChildren,\n      );\n    }\n\n    render(<Example />, container);\n\n    expect(container.innerHTML).toBe(\n      '<div>First</div><div>Sub1</div><div>Sub2</div><div>second</div>',\n    );\n\n    render(<FunctionalComp />, container);\n\n    expect(container.innerHTML).toBe('<div>Functional</div>');\n\n    render(<Example />, container);\n\n    expect(container.innerHTML).toBe(\n      '<div>First</div><div>Sub1</div><div>Sub2</div><div>second</div>',\n    );\n\n    render(<FunctionalComp />, container);\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be possible to move fragments', () => {\n    const fragmentA = () =>\n      createFragment(\n        [<div id=\"a1\">A1</div>, <div>A2</div>],\n        ChildFlags.HasNonKeyedChildren,\n        'A',\n      );\n\n    const fragmentB = () =>\n      createFragment(\n        [<div id=\"b1\">B1</div>],\n        ChildFlags.HasNonKeyedChildren,\n        'B',\n      );\n\n    const fragmentC = () =>\n      createFragment(\n        [<div id=\"c1\">C1</div>, <div>C2</div>, <div>C3</div>],\n        ChildFlags.HasNonKeyedChildren,\n        'C',\n      );\n\n    render(\n      <div>\n        {fragmentA()}\n        {fragmentB()}\n        {fragmentC()}\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div id=\"a1\">A1</div><div>A2</div><div id=\"b1\">B1</div><div id=\"c1\">C1</div><div>C2</div><div>C3</div></div>',\n    );\n\n    const A1 = container.querySelector('#a1');\n    const B1 = container.querySelector('#b1');\n    const C1 = container.querySelector('#c1');\n\n    // Switch order\n    render(\n      <div>\n        {fragmentC()}\n        {fragmentA()}\n        {fragmentB()}\n      </div>,\n      container,\n    );\n\n    // Verify dom has changed and nodes are the same\n    expect(container.innerHTML).toBe(\n      '<div><div id=\"c1\">C1</div><div>C2</div><div>C3</div><div id=\"a1\">A1</div><div>A2</div><div id=\"b1\">B1</div></div>',\n    );\n\n    expect(container.querySelector('#a1')).toBe(A1);\n    expect(container.querySelector('#b1')).toBe(B1);\n    expect(container.querySelector('#c1')).toBe(C1);\n\n    // Switch order again\n    render(\n      <div>\n        {fragmentB()}\n        {fragmentC()}\n      </div>,\n      container,\n    );\n\n    // Verify dom has changed and nodes are the same\n    expect(container.innerHTML).toBe(\n      '<div><div id=\"b1\">B1</div><div id=\"c1\">C1</div><div>C2</div><div>C3</div></div>',\n    );\n\n    expect(container.querySelector('#a1')).toBe(null);\n    expect(container.querySelector('#b1')).toBe(B1);\n    expect(container.querySelector('#c1')).toBe(C1);\n  });\n\n  it('Should clone fragment children if they are passed as reference', () => {\n    const fragmentA = createFragment(\n      [<div id=\"a1\">A1</div>, <div>A2</div>],\n      ChildFlags.HasNonKeyedChildren,\n      'A',\n    );\n    const fragmentB = createFragment(\n      [<div id=\"b1\">B1</div>],\n      ChildFlags.HasNonKeyedChildren,\n      'B',\n    );\n    const fragmentC = createFragment(\n      [<div id=\"c1\">C1</div>, <div>C2</div>, <div>C3</div>],\n      ChildFlags.HasNonKeyedChildren,\n      'C',\n    );\n\n    const content = [fragmentC];\n\n    function SFC() {\n      return (\n        <Fragment>\n          <span>1</span>\n          <Fragment>{content}</Fragment>\n          <span>2</span>\n        </Fragment>\n      );\n    }\n\n    render(\n      <Fragment>\n        {fragmentA}\n        <SFC key=\"sfc\" />\n        {fragmentB}\n        {fragmentC}\n      </Fragment>,\n      container,\n    );\n\n    const FragmentAHtml = '<div id=\"a1\">A1</div><div>A2</div>';\n    const FragmentBHtml = '<div id=\"b1\">B1</div>';\n    const FragmentCHtml = '<div id=\"c1\">C1</div><div>C2</div><div>C3</div>';\n    const SFCHtml = '<span>1</span>' + FragmentCHtml + '<span>2</span>';\n\n    expect(container.innerHTML).toBe(\n      FragmentAHtml + SFCHtml + FragmentBHtml + FragmentCHtml,\n    );\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be possible to move component with fragment root', () => {\n    const fragmentA = createFragment(\n      [<div id=\"a1\">A1</div>, <div>A2</div>],\n      ChildFlags.HasNonKeyedChildren,\n      'A',\n    );\n    const fragmentB = createFragment(\n      [<div id=\"b1\">B1</div>],\n      ChildFlags.HasNonKeyedChildren,\n      'B',\n    );\n    const fragmentC = createFragment(\n      [<div id=\"c1\">C1</div>, <div>C2</div>, <div>C3</div>],\n      ChildFlags.HasNonKeyedChildren,\n      'C',\n    );\n\n    const content = [fragmentC];\n\n    function SFC() {\n      return (\n        <Fragment>\n          <span>1</span>\n          <Fragment>{content}</Fragment>\n          <span>2</span>\n        </Fragment>\n      );\n    }\n\n    render(\n      <Fragment>\n        {fragmentA}\n        <SFC key=\"sfc\" />\n        {fragmentB}\n        {fragmentC}\n      </Fragment>,\n      container,\n    );\n\n    const FragmentAHtml = '<div id=\"a1\">A1</div><div>A2</div>';\n    const FragmentBHtml = '<div id=\"b1\">B1</div>';\n    const FragmentCHtml = '<div id=\"c1\">C1</div><div>C2</div><div>C3</div>';\n    const SFCHtml = '<span>1</span>' + FragmentCHtml + '<span>2</span>';\n\n    expect(container.innerHTML).toBe(\n      FragmentAHtml + SFCHtml + FragmentBHtml + FragmentCHtml,\n    );\n\n    // Switch order\n    render(\n      <Fragment>\n        {fragmentA}\n        {fragmentC}\n        <SFC key=\"sfc\" />\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(FragmentAHtml + FragmentCHtml + SFCHtml);\n\n    // Switch order again\n    render(\n      <Fragment>\n        <div key=\"1\">1</div>\n        <SFC key=\"sfc\" />\n        {fragmentA}\n        {fragmentC}\n        <div key=\"1\">2</div>\n      </Fragment>,\n      container,\n    );\n\n    // Verify dom has changed and nodes are the same\n    expect(container.innerHTML).toBe(\n      '<div>1</div>' + SFCHtml + FragmentAHtml + FragmentCHtml + '<div>2</div>',\n    );\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be possible to move component with fragment root #2', () => {\n    const fragmentA = createFragment(\n      [<div id=\"a1\">A1</div>, <div>A2</div>],\n      ChildFlags.HasNonKeyedChildren,\n      'A',\n    );\n    const fragmentB = createFragment(\n      [<div id=\"b1\">B1</div>],\n      ChildFlags.HasNonKeyedChildren,\n      'B',\n    );\n    const fragmentC = createFragment(\n      [<div id=\"c1\">C1</div>, <div>C2</div>, <div>C3</div>],\n      ChildFlags.HasNonKeyedChildren,\n      'C',\n    );\n\n    const content = [fragmentC];\n\n    function SFC() {\n      return (\n        <Fragment>\n          <span>1</span>\n          <Fragment>{content}</Fragment>\n          <span>2</span>\n        </Fragment>\n      );\n    }\n\n    render(\n      <Fragment>\n        {fragmentA}\n        <SFC key=\"sfc1\" />\n        {fragmentB}\n        <SFC key=\"sfc2\" />\n        {fragmentC}\n        <SFC key=\"sfc3\" />\n      </Fragment>,\n      container,\n    );\n\n    const FragmentAHtml = '<div id=\"a1\">A1</div><div>A2</div>';\n    const FragmentBHtml = '<div id=\"b1\">B1</div>';\n    const FragmentCHtml = '<div id=\"c1\">C1</div><div>C2</div><div>C3</div>';\n    const SFCHtml = '<span>1</span>' + FragmentCHtml + '<span>2</span>';\n\n    expect(container.innerHTML).toBe(\n      FragmentAHtml +\n        SFCHtml +\n        FragmentBHtml +\n        SFCHtml +\n        FragmentCHtml +\n        SFCHtml,\n    );\n\n    // Switch order\n    render(\n      <Fragment>\n        <SFC key=\"sfc3\" />\n        {fragmentA}\n        <SFC key=\"sfc1\" />\n        {fragmentC}\n        <SFC key=\"sfc2\" />\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      SFCHtml + FragmentAHtml + SFCHtml + FragmentCHtml + SFCHtml,\n    );\n\n    // Switch order again\n    render(\n      <Fragment>\n        <div key=\"1\">1</div>\n        <SFC key=\"sfc1\" />\n        <SFC key=\"sfc2\" />\n        {fragmentA}\n        {fragmentC}\n        <div key=\"1\">2</div>\n        <SFC key=\"sfc3\" />\n      </Fragment>,\n      container,\n    );\n\n    // Verify dom has changed and nodes are the same\n    expect(container.innerHTML).toBe(\n      '<div>1</div>' +\n        SFCHtml +\n        SFCHtml +\n        FragmentAHtml +\n        FragmentCHtml +\n        '<div>2</div>' +\n        SFCHtml,\n    );\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be possible to render fragments JSX way', () => {\n    interface FragmenterProps {\n      first: InfernoNode;\n      mid: InfernoNode;\n      last: InfernoNode;\n      changeOrder?: boolean;\n    }\n\n    function Fragmenter({ first, mid, last, changeOrder }: FragmenterProps) {\n      if (changeOrder) {\n        return (\n          <>\n            <div>{first}</div>\n            <>\n              More\n              {null}\n              Hey!\n              <Fragment>\n                <>Large {last}</>\n                <Fragment>And Small</Fragment>\n              </Fragment>\n              <>Nesting</>\n              {mid}\n            </>\n            <span>bar</span>\n            {null}\n          </>\n        );\n      }\n      return (\n        <>\n          <div>{first}</div>\n          Hey!\n          <>\n            More\n            <>Nesting</>\n            {mid}\n            <Fragment>\n              <>Large {last}</>\n              <Fragment>And Small</Fragment>\n            </Fragment>\n          </>\n          <span>bar</span>\n        </>\n      );\n    }\n\n    let mountCounter = 0;\n    let unmountCounter = 0;\n\n    interface FoobarComProps {\n      node: HTMLDivElement;\n    }\n\n    class FoobarCom extends Component<FoobarComProps> {\n      public componentWillMount() {\n        mountCounter++;\n      }\n\n      public componentWillUnmount() {\n        unmountCounter++;\n      }\n\n      public render(props) {\n        return (\n          <>\n            {props.children}\n            {createPortal(<div>InvisiblePortalCreator</div>, props.node)}\n            {null}\n            Try out some crazy stuff\n          </>\n        );\n      }\n    }\n\n    const portalNode = document.createElement('div');\n\n    render(\n      <FoobarCom node={portalNode}>\n        <Fragmenter first=\"first\" mid=\"MID\" last={<div>Why?</div>} />\n      </FoobarCom>,\n      container,\n    );\n\n    expect(mountCounter).toBe(1);\n    expect(unmountCounter).toBe(0);\n    expect(container.innerHTML).toBe(\n      '<div>first</div>Hey!MoreNestingMIDLarge <div>Why?</div>And Small<span>bar</span>Try out some crazy stuff',\n    );\n    expect(portalNode.innerHTML).toBe('<div>InvisiblePortalCreator</div>');\n\n    render(\n      <FoobarCom node={portalNode}>\n        <Fragmenter\n          first={<span>GoGo</span>}\n          mid=\"MID\"\n          last={<div>Why?</div>}\n          changeOrder={true}\n        />\n      </FoobarCom>,\n      container,\n    );\n\n    expect(mountCounter).toBe(1);\n    expect(unmountCounter).toBe(0);\n    expect(container.innerHTML).toBe(\n      '<div><span>GoGo</span></div>MoreHey!Large <div>Why?</div>And SmallNestingMID<span>bar</span>Try out some crazy stuff',\n    );\n    expect(portalNode.innerHTML).toBe('<div>InvisiblePortalCreator</div>');\n\n    render(\n      <FoobarCom node={portalNode}>\n        <Fragmenter first=\"first\" mid=\"MID\" last={<div>Why?</div>} />\n      </FoobarCom>,\n      container,\n    );\n    expect(mountCounter).toBe(1);\n    expect(unmountCounter).toBe(0);\n    expect(container.innerHTML).toBe(\n      '<div>first</div>Hey!MoreNestingMIDLarge <div>Why?</div>And Small<span>bar</span>Try out some crazy stuff',\n    );\n    expect(portalNode.innerHTML).toBe('<div>InvisiblePortalCreator</div>');\n  });\n\n  it('Should render deeply nested fragment', () => {\n    function Fragmenter2() {\n      return (\n        <>\n          <>\n            <>\n              <>\n                <>\n                  <>\n                    <>\n                      <>Okay!</>\n                    </>\n                  </>\n                </>\n              </>\n            </>\n          </>\n        </>\n      );\n    }\n\n    render(<Fragmenter2 />, container);\n\n    expect(container.innerHTML).toBe('Okay!');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should append DOM nodes to correct position when component root Fragmnet change', () => {\n    class TestRoot extends Component {\n      public render() {\n        return <>{this.props.children}</>;\n      }\n    }\n\n    render(\n      <div>\n        <TestRoot>\n          <div>1</div>\n          <div>2</div>\n        </TestRoot>\n        <TestRoot>\n          <span>Ok</span>\n          <span>Test</span>\n        </TestRoot>\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div>1</div><div>2</div><span>Ok</span><span>Test</span></div>',\n    );\n\n    render(\n      <div>\n        <TestRoot>\n          <div>1</div>\n          <div>2</div>\n          <div>3</div>\n          <div>4</div>\n        </TestRoot>\n        <TestRoot>\n          <div>Other</div>\n        </TestRoot>\n      </div>,\n      container,\n    );\n    expect(container.innerHTML).toBe(\n      '<div><div>1</div><div>2</div><div>3</div><div>4</div><div>Other</div></div>',\n    );\n  });\n\n  it('Should not clear whole parent element when fragment children are cleared', () => {\n    class TestRoot extends Component {\n      public render() {\n        return <>{this.props.children}</>;\n      }\n    }\n\n    render(\n      <div>\n        <TestRoot>\n          <div>1</div>\n          <div>2</div>\n        </TestRoot>\n        <TestRoot>\n          <span>Ok</span>\n          <span>Test</span>\n        </TestRoot>\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div>1</div><div>2</div><span>Ok</span><span>Test</span></div>',\n    );\n\n    render(\n      <div>\n        <TestRoot>\n          <div>1</div>\n          <div>2</div>\n          <div>3</div>\n          <div>4</div>\n        </TestRoot>\n        <TestRoot />\n      </div>,\n      container,\n    );\n    expect(container.innerHTML).toBe(\n      '<div><div>1</div><div>2</div><div>3</div><div>4</div></div>',\n    );\n  });\n\n  it('Should move fragment and all its contents when using Fragment long syntax with keys', () => {\n    let unmountCounter = 0;\n    let mountCounter = 0;\n\n    class TestLifecycle extends Component {\n      public componentWillUnmount() {\n        unmountCounter++;\n      }\n\n      public componentWillMount() {\n        mountCounter++;\n      }\n\n      public render() {\n        return <>{this.props.children}</>;\n      }\n    }\n\n    render(\n      <div>\n        <Fragment key=\"1\">\n          <TestLifecycle>1a</TestLifecycle>\n          <TestLifecycle>1b</TestLifecycle>\n        </Fragment>\n        <Fragment key=\"2\">\n          <TestLifecycle>2a</TestLifecycle>\n          <TestLifecycle>2b</TestLifecycle>\n        </Fragment>\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div>1a1b2a2b</div>');\n    expect(unmountCounter).toBe(0);\n    expect(mountCounter).toBe(4);\n\n    render(\n      <div>\n        <Fragment key=\"2\">\n          <TestLifecycle>2a</TestLifecycle>\n          <TestLifecycle>2b</TestLifecycle>\n          <TestLifecycle>2c</TestLifecycle>\n        </Fragment>\n        <Fragment key=\"1\">\n          <TestLifecycle>1a</TestLifecycle>\n          <TestLifecycle>1b</TestLifecycle>\n        </Fragment>\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div>2a2b2c1a1b</div>');\n    expect(unmountCounter).toBe(0);\n    expect(mountCounter).toBe(5);\n\n    render(\n      <div>\n        <Fragment key=\"3\">\n          <TestLifecycle>3a</TestLifecycle>\n          <TestLifecycle>3b</TestLifecycle>\n          <TestLifecycle>3c</TestLifecycle>\n        </Fragment>\n        <Fragment key=\"2\">\n          <TestLifecycle>2a</TestLifecycle>\n          <TestLifecycle>2Patched</TestLifecycle>\n        </Fragment>\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div>3a3b3c2a2Patched</div>');\n    expect(unmountCounter).toBe(3);\n    expect(mountCounter).toBe(8);\n  });\n\n  it('Should unmount empty fragments', () => {\n    render(\n      <Fragment>\n        <Fragment />\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('');\n\n    render(\n      <Fragment>\n        <div />\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div></div>');\n\n    render(\n      <Fragment>\n        <Fragment />\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be possible to replace last element in fragment', () => {\n    render(\n      <Fragment>\n        <Fragment>\n          <span>1a</span>\n          <span>1b</span>\n          <div>1c</div>\n        </Fragment>\n        <Fragment>\n          <span>2a</span>\n          <span>2b</span>\n          <span>2c</span>\n        </Fragment>\n        <Fragment />\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<span>1a</span><span>1b</span><div>1c</div><span>2a</span><span>2b</span><span>2c</span>',\n    );\n\n    render(\n      <Fragment>\n        <Fragment>\n          <span>1a</span>\n          <span>1c</span>\n        </Fragment>\n        <Fragment>\n          <span>2a</span>\n          <span>2b</span>\n          <span>2c</span>\n        </Fragment>\n        <Fragment />\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<span>1a</span><span>1c</span><span>2a</span><span>2b</span><span>2c</span>',\n    );\n\n    render(\n      <Fragment>\n        <Fragment />\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should mount Fragment with invalid children', () => {\n    render(\n      <Fragment>\n        {null}\n        {undefined}\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should mount Fragment with invalid children #2', () => {\n    function Foobar() {\n      return null;\n    }\n\n    render(\n      <Fragment>\n        {null}\n        <Foobar />\n        {undefined}\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should mount Fragment with invalid children #2', () => {\n    let add = false;\n\n    function Foobar() {\n      if (add) {\n        return <div>Ok</div>;\n      }\n      return null;\n    }\n\n    render(\n      <Fragment>\n        {null}\n        <Foobar />\n        {undefined}\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('');\n\n    add = true;\n\n    render(\n      <Fragment>\n        {null}\n        <Foobar />\n        {undefined}\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div>Ok</div>');\n  });\n\n  it('Should be possible to update from 0 to 1', () => {\n    function Foobar() {\n      return <div>Ok</div>;\n    }\n\n    let content = [null];\n\n    render(\n      <Fragment>\n        <span>1</span>\n        <Fragment>{content}</Fragment>\n        <span>2</span>\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<span>1</span><span>2</span>');\n\n    content = [<Foobar />];\n\n    render(\n      <Fragment>\n        <span>1</span>\n        <Fragment>{content}</Fragment>\n        <span>2</span>\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<span>1</span><div>Ok</div><span>2</span>',\n    );\n  });\n\n  it('Should be possible to update from 0 to 1 fragment -> fragment', () => {\n    function Foobar() {\n      return <div>Ok</div>;\n    }\n\n    let content: InfernoNode[] = [];\n\n    render(\n      <Fragment>\n        <span>1</span>\n        <Fragment>{content}</Fragment>\n        <span>2</span>\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<span>1</span><span>2</span>');\n\n    content = [\n      <Fragment>\n        <Foobar />\n      </Fragment>,\n    ];\n\n    render(\n      <Fragment>\n        <span>1</span>\n        <Fragment>{content}</Fragment>\n        <span>2</span>\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<span>1</span><div>Ok</div><span>2</span>',\n    );\n  });\n\n  it('Should be possible to mount and patch single component fragment children', () => {\n    let counter = 0;\n\n    class Foobar extends Component {\n      public componentWillMount() {\n        counter++;\n      }\n\n      public render() {\n        return null;\n      }\n    }\n\n    render(<></>, container);\n\n    render(\n      <>\n        <Foobar />\n      </>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('');\n    expect(counter).toBe(1);\n\n    render(\n      <>\n        <div>Ok</div>\n        <Foobar />\n      </>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div>Ok</div>');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be possible to mount and patch single component fragment children - variation 2', () => {\n    let counter = 0;\n\n    class Foobar extends Component {\n      public componentWillMount() {\n        counter++;\n      }\n\n      public render() {\n        return null;\n      }\n    }\n\n    let nodes: InfernoNode[] = [];\n\n    render(<>{nodes}</>, container);\n\n    nodes = [<Foobar />];\n\n    render(<>{nodes}</>, container);\n\n    nodes = [<Foobar />, <Foobar />, <Foobar />];\n\n    render(<>{nodes}</>, container);\n\n    nodes = [];\n\n    render(<>{nodes}</>, container);\n\n    expect(container.innerHTML).toBe('');\n    expect(counter).toBe(3);\n\n    render(\n      <>\n        <div>Ok</div>\n        <Foobar />\n      </>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div>Ok</div>');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be possible to patch single fragment child component', () => {\n    let counter = 0;\n\n    class Foobar extends Component {\n      public componentWillMount() {\n        counter++;\n      }\n\n      public render() {\n        return null;\n      }\n    }\n\n    render(\n      <>\n        <>\n          <Foobar />\n        </>\n        <>\n          <Foobar />\n        </>\n      </>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('');\n    expect(counter).toBe(2);\n\n    render(\n      <>\n        <></>\n        <>\n          <Foobar />\n        </>\n        <>\n          <Foobar />\n        </>\n        <></>\n        <Foobar />\n      </>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('');\n    expect(counter).toBe(4);\n\n    render(\n      <>\n        <div>Ok</div>\n        <Foobar />\n      </>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div>Ok</div>');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be possible to mount and patch single component fragment children', () => {\n    class Foobar extends Component {\n      public render() {\n        return null;\n      }\n    }\n\n    render(\n      <>\n        <Foobar />\n      </>,\n      container,\n    );\n\n    render(\n      <>\n        <Foobar />\n      </>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('');\n\n    render(\n      <>\n        <div>Ok</div>\n        <Foobar />\n      </>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div>Ok</div>');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be possible to mount and patch single component fragment children', () => {\n    class Foobar extends Component {\n      public render() {\n        return null;\n      }\n    }\n\n    render(<>{null}</>, container);\n\n    render(\n      <>\n        <Foobar />\n      </>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('');\n\n    render(\n      <>\n        <div>Ok</div>\n        <Foobar />\n      </>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div>Ok</div>');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should render fragment inside fragment Github #1399', () => {\n    function Layout(props) {\n      return <>{props.children}</>;\n    }\n\n    class PageTemplate extends Component {\n      public test(sim) {\n        return (\n          <>\n            <div>{sim}</div>\n          </>\n        );\n      }\n\n      public render() {\n        return (\n          <Layout>\n            <div>test</div>\n            <>{this.test('sim')}</>\n          </Layout>\n        );\n      }\n    }\n\n    render(<PageTemplate />, container);\n\n    expect(container.innerHTML).toBe('<div>test</div><div>sim</div>');\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should not crash if lastFragment is empty and optimized for keyed ( mount )', () => {\n    let nodes: InfernoKeyedNode[] = [];\n\n    render(<Fragment $HasKeyedChildren>{nodes}</Fragment>, container);\n\n    expect(container.innerHTML).toBe('');\n\n    nodes = [<h1 key=\"1\">Hello</h1>, <h2 key=\"2\">InfernoJS</h2>];\n\n    render(<Fragment $HasKeyedChildren>{nodes}</Fragment>, container);\n\n    expect(container.innerHTML).toBe('<h1>Hello</h1><h2>InfernoJS</h2>');\n  });\n\n  it('Should not crash if lastFragment is empty and optimized for keyed ( patch )', () => {\n    let nodes: InfernoNode[] = [];\n\n    render(<Fragment $HasKeyedChildren>{nodes}</Fragment>, container);\n\n    expect(container.innerHTML).toBe('');\n\n    nodes = nodes.slice();\n\n    render(<Fragment $HasKeyedChildren>{nodes}</Fragment>, container);\n\n    expect(container.innerHTML).toBe('');\n\n    nodes = [<h1 key=\"1\">Hello</h1>, <h2 key=\"2\">InfernoJS</h2>];\n\n    render(<Fragment $HasKeyedChildren>{nodes}</Fragment>, container);\n\n    expect(container.innerHTML).toBe('<h1>Hello</h1><h2>InfernoJS</h2>');\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/hooks.spec.tsx",
    "content": "import { Component, render } from 'inferno';\nimport Spy = jasmine.Spy;\n\ndescribe('Component lifecycle (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('componentWillUnmount', () => {\n    it('Should trigger UnMount for all children', () => {\n      let updater: (() => void) | null = null;\n\n      interface AState {\n        foo: boolean;\n      }\n\n      class A extends Component<unknown, AState> {\n        public state: AState;\n\n        public componentWillUnmount() {}\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            foo: true,\n          };\n\n          this.updateme = this.updateme.bind(this);\n          updater = this.updateme;\n        }\n\n        public updateme() {\n          this.setState({\n            foo: !this.state.foo,\n          });\n        }\n\n        public render() {\n          return (\n            <div>\n              {(() => {\n                if (this.state.foo) {\n                  return null;\n                }\n                return <B />;\n              })()}\n              <button onClick={this.updateme}>btn</button>\n            </div>\n          );\n        }\n      }\n\n      class B extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return (\n            <div>\n              <C />\n            </div>\n          );\n        }\n      }\n\n      class C extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return (\n            <div>\n              <D />\n            </div>\n          );\n        }\n      }\n\n      class D extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <div>Terve</div>;\n        }\n      }\n\n      const Aspy = spyOn(A.prototype, 'componentWillUnmount');\n      const Bspy = spyOn(B.prototype, 'componentWillUnmount');\n      const CSpy = spyOn(C.prototype, 'componentWillUnmount');\n      const DSpy = spyOn(D.prototype, 'componentWillUnmount');\n\n      render(<A />, container);\n      expect(container.innerHTML).toBe('<div><button>btn</button></div>');\n      expect(Aspy).not.toHaveBeenCalled();\n      expect(Bspy).not.toHaveBeenCalled();\n      expect(CSpy).not.toHaveBeenCalled();\n      expect(DSpy).not.toHaveBeenCalled();\n\n      updater!();\n      expect(container.innerHTML).toBe(\n        '<div><div><div><div>Terve</div></div></div><button>btn</button></div>',\n      );\n      expect(Aspy).not.toHaveBeenCalled();\n      expect(Bspy).not.toHaveBeenCalled();\n      expect(CSpy).not.toHaveBeenCalled();\n      expect(DSpy).not.toHaveBeenCalled();\n\n      updater!();\n      expect(container.innerHTML).toBe('<div><button>btn</button></div>');\n      expect(Aspy).not.toHaveBeenCalled();\n      expect(Bspy).toHaveBeenCalledTimes(1);\n      expect(CSpy).toHaveBeenCalledTimes(1);\n      expect(DSpy).toHaveBeenCalledTimes(1);\n    });\n\n    it('Should not trigger unmount for new node', () => {\n      let updater: (() => void) | null = null;\n\n      interface AState {\n        foo: boolean;\n      }\n\n      class A extends Component<unknown, AState> {\n        public state: AState;\n        public componentWillUnmount() {}\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            foo: true,\n          };\n\n          this.updateme = this.updateme.bind(this);\n          updater = this.updateme;\n        }\n\n        public updateme() {\n          this.setState({\n            foo: !this.state.foo,\n          });\n        }\n\n        public render() {\n          return (\n            <div>\n              {(() => {\n                if (this.state.foo) {\n                  return null;\n                }\n                return <B />;\n              })()}\n              <button onClick={this.updateme}>btn</button>\n            </div>\n          );\n        }\n      }\n\n      class B extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <C />;\n        }\n      }\n\n      class C extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <D />;\n        }\n      }\n\n      class D extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <div>Terve</div>;\n        }\n      }\n\n      const Aspy = spyOn(A.prototype, 'componentWillUnmount');\n      const Bspy = spyOn(B.prototype, 'componentWillUnmount');\n      const CSpy = spyOn(C.prototype, 'componentWillUnmount');\n      const DSpy = spyOn(D.prototype, 'componentWillUnmount');\n\n      render(<A />, container);\n      expect(container.innerHTML).toBe('<div><button>btn</button></div>');\n      expect(Aspy).not.toHaveBeenCalled();\n      expect(Bspy).not.toHaveBeenCalled();\n      expect(CSpy).not.toHaveBeenCalled();\n      expect(DSpy).not.toHaveBeenCalled();\n\n      updater!();\n      expect(container.innerHTML).toBe(\n        '<div><div>Terve</div><button>btn</button></div>',\n      );\n      expect(Aspy).not.toHaveBeenCalled();\n      expect(Bspy).not.toHaveBeenCalled();\n      expect(CSpy).not.toHaveBeenCalled();\n      expect(DSpy).not.toHaveBeenCalled();\n\n      updater!();\n      expect(container.innerHTML).toBe('<div><button>btn</button></div>');\n      expect(Aspy).not.toHaveBeenCalled();\n      expect(Bspy).toHaveBeenCalledTimes(1);\n      expect(CSpy).toHaveBeenCalledTimes(1);\n      expect(DSpy).toHaveBeenCalledTimes(1);\n    });\n\n    it('Should trigger unMount once for direct nested children', () => {\n      class B extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <div>B</div>;\n        }\n      }\n\n      class C extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <div>C</div>;\n        }\n      }\n\n      class D extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <div>D</div>;\n        }\n      }\n\n      const Bspy = spyOn(B.prototype, 'componentWillUnmount');\n      const CSpy = spyOn(C.prototype, 'componentWillUnmount');\n      const DSpy = spyOn(D.prototype, 'componentWillUnmount');\n\n      render(<B />, container);\n      expect(container.innerHTML).toBe('<div>B</div>');\n      expect(Bspy).not.toHaveBeenCalled();\n      expect(CSpy).not.toHaveBeenCalled();\n      expect(DSpy).not.toHaveBeenCalled();\n\n      render(<C />, container);\n      expect(container.innerHTML).toBe('<div>C</div>');\n      expect(Bspy).toHaveBeenCalledTimes(1);\n      expect(CSpy).not.toHaveBeenCalled();\n      expect(DSpy).not.toHaveBeenCalled();\n\n      render(<D />, container);\n      expect(container.innerHTML).toBe('<div>D</div>');\n      expect(Bspy).toHaveBeenCalledTimes(1);\n      expect(CSpy).toHaveBeenCalledTimes(1);\n      expect(DSpy).not.toHaveBeenCalled();\n\n      render(<B />, container);\n      expect(container.innerHTML).toBe('<div>B</div>');\n      expect(Bspy).toHaveBeenCalledTimes(1);\n      expect(CSpy).toHaveBeenCalledTimes(1);\n      expect(DSpy).toHaveBeenCalledTimes(1);\n    });\n\n    it('Should trigger unmount once for children', () => {\n      class B extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return (\n            <div>\n              <B1 />\n              <B2 />\n            </div>\n          );\n        }\n      }\n\n      class B1 extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <p>B1</p>;\n        }\n      }\n\n      class B2 extends Component {\n        public componentWillUnmount() {}\n\n        public render() {\n          return <p>B2</p>;\n        }\n      }\n\n      class C extends Component {\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            text: 'C0',\n          };\n\n          this.updateMe = this.updateMe.bind(this);\n        }\n\n        public componentWillUnmount() {}\n\n        public updateMe() {\n          this.setState({\n            text: 'C1',\n          });\n        }\n\n        public render() {\n          return (\n            <div className=\"c\">\n              <C1 />\n              <C2 />\n            </div>\n          );\n        }\n      }\n\n      class C1 extends Component {\n        public render() {\n          return <p>C1</p>;\n        }\n      }\n\n      class C2 extends Component {\n        public render() {\n          return <p>C2</p>;\n        }\n      }\n\n      const Bspy = spyOn(B.prototype, 'componentWillUnmount');\n      const B1spy = spyOn(B1.prototype, 'componentWillUnmount');\n      const B2spy = spyOn(B2.prototype, 'componentWillUnmount');\n      const CSpy = spyOn(C.prototype, 'componentWillUnmount');\n\n      render(<B />, container);\n      expect(container.innerHTML).toBe('<div><p>B1</p><p>B2</p></div>');\n      expect(Bspy).not.toHaveBeenCalled();\n      expect(B1spy).not.toHaveBeenCalled();\n      expect(B2spy).not.toHaveBeenCalled();\n      expect(CSpy).not.toHaveBeenCalled();\n\n      Bspy.calls.reset();\n      B1spy.calls.reset();\n      B2spy.calls.reset();\n      CSpy.calls.reset();\n\n      render(<C />, container);\n      expect(container.innerHTML).toBe(\n        '<div class=\"c\"><p>C1</p><p>C2</p></div>',\n      );\n      expect(Bspy).toHaveBeenCalledTimes(1);\n      expect(B1spy).toHaveBeenCalledTimes(1);\n      expect(B2spy).toHaveBeenCalledTimes(1);\n    });\n  });\n\n  describe('Stateless component hooks', () => {\n    let _container;\n\n    function StatelessComponent(_props: { a?: unknown }) {\n      return <div>Hello world</div>;\n    }\n\n    afterEach(function () {\n      render(null, _container);\n    });\n\n    beforeEach(function () {\n      _container = document.createElement('div');\n    });\n\n    it('\"onComponentWillMount\" hook should fire, args props', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      render(\n        <StatelessComponent a={1} onComponentWillMount={spyObj.fn} />,\n        _container,\n      );\n\n      expect(spy.calls.count()).toBe(1);\n      expect(spy.calls.argsFor(0).length).toBe(1);\n      expect(spy.calls.argsFor(0)[0]).toEqual({ a: 1 });\n    });\n\n    it('\"onComponentDidMount\" hook should fire, args DOM props', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      render(\n        <StatelessComponent a={1} onComponentDidMount={spyObj.fn} />,\n        _container,\n      );\n\n      expect(spy.calls.count()).toBe(1);\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0]).toBe(_container.firstChild);\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 1 });\n    });\n\n    it('\"onComponentWillUnmount\" hook should fire, args DOM props', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      render(\n        <StatelessComponent a={1} onComponentWillUnmount={spyObj.fn} />,\n        _container,\n      );\n      expect(spy.calls.count()).toBe(0);\n      // do unmount\n      render(null, _container);\n\n      expect(spy.calls.count()).toBe(1);\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0].outerHTML).toBe('<div>Hello world</div>');\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 1 });\n    });\n\n    it('\"onComponentWillUpdate\" hook should fire, args props nextProps', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      render(\n        <StatelessComponent a={1} onComponentWillUpdate={spyObj.fn} />,\n        _container,\n      );\n      expect(spy.calls.count()).toBe(0); // Update 1\n      render(\n        <StatelessComponent a={2} onComponentWillUpdate={spyObj.fn} />,\n        _container,\n      );\n      expect(spy.calls.count()).toBe(1); // Update 2\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0]).toEqual({ a: 1 });\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 2 });\n    });\n\n    it('\"onComponentDidUpdate\" hook should fire, args prevProps props', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      render(\n        <StatelessComponent a={1} onComponentDidUpdate={spyObj.fn} />,\n        _container,\n      );\n      expect(spy.calls.count()).toBe(0); // Update 1\n      render(\n        <StatelessComponent a={2} onComponentDidUpdate={spyObj.fn} />,\n        _container,\n      );\n      expect(spy.calls.count()).toBe(1); // Update 2\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0]).toEqual({ a: 1 });\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 2 });\n    });\n\n    it('\"onComponentShouldUpdate\" hook should fire, should call render when return true, args props nextProps', () => {\n      let onComponentShouldUpdateCount = 0;\n      let renderCount = 0;\n      const spyObj = {\n        fn: () => {\n          onComponentShouldUpdateCount++;\n          return true;\n        },\n      };\n      const spy = spyOn(spyObj, 'fn').and.callThrough();\n      const StatelessComponent3 = (_props: { a?: unknown }) => {\n        renderCount++;\n        return null;\n      };\n\n      render(\n        <StatelessComponent3 a={1} onComponentShouldUpdate={spyObj.fn} />,\n        _container,\n      );\n      expect(onComponentShouldUpdateCount).toBe(0); // Update 1\n      expect(renderCount).toBe(1); // Rendered 1 time\n\n      render(\n        <StatelessComponent3 a={2} onComponentShouldUpdate={spyObj.fn} />,\n        _container,\n      );\n      expect(onComponentShouldUpdateCount).toBe(1); // Update 2\n      expect(renderCount).toBe(2); // Rendered 2 time\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0]).toEqual({ a: 1 });\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 2 });\n    });\n\n    it('\"onComponentShouldUpdate\" hook should fire, should not call render when return false, args props nextProps', () => {\n      let onComponentShouldUpdateCount = 0;\n      let renderCount = 0;\n      const spyObj = {\n        fn: () => {\n          onComponentShouldUpdateCount++;\n          return false;\n        },\n      };\n      const spy = spyOn(spyObj, 'fn').and.callThrough();\n      const StatelessComponent2 = (_props: { a?: unknown }) => {\n        renderCount++;\n        return null;\n      };\n\n      render(\n        <StatelessComponent2 a={1} onComponentShouldUpdate={spyObj.fn} />,\n        _container,\n      );\n      expect(onComponentShouldUpdateCount).toBe(0); // Update 1\n      expect(renderCount).toBe(1); // Rendered 1 time\n\n      render(\n        <StatelessComponent2 a={2} onComponentShouldUpdate={spyObj.fn} />,\n        _container,\n      );\n      expect(onComponentShouldUpdateCount).toBe(1); // Update 2\n      expect(renderCount).toBe(1); // Rendered 1 time\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0]).toEqual({ a: 1 });\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 2 });\n    });\n  });\n\n  describe('ref hook', () => {\n    const fakeObj = {\n      previousSiblingCallback() {},\n      innerCallback() {},\n      innerSecondCallback() {},\n    };\n\n    const RefTester = ({ inner, innersecond }) => {\n      let content = null;\n      if (inner) {\n        let contentTwo = null;\n        if (innersecond) {\n          contentTwo = <span ref={fakeObj.innerSecondCallback}>dfg</span>;\n        }\n        content = <div ref={fakeObj.innerCallback}>{contentTwo}</div>;\n      }\n\n      return (\n        <div>\n          <span ref={fakeObj.previousSiblingCallback}>abc</span>\n          {content}\n        </div>\n      );\n    };\n\n    let orderOfCalls: string[] = [];\n    let spyPreviousSibling = null as unknown as Spy;\n    let spyInner = null as unknown as Spy;\n    let spyInnerSecond = null as unknown as Spy;\n\n    beforeEach(function () {\n      orderOfCalls = [];\n      spyPreviousSibling = spyOn(\n        fakeObj,\n        'previousSiblingCallback',\n      ).and.callFake(function () {\n        orderOfCalls.push('spyPreviousSibling');\n      });\n      spyInner = spyOn(fakeObj, 'innerCallback').and.callFake(function () {\n        orderOfCalls.push('inner');\n      });\n      spyInnerSecond = spyOn(fakeObj, 'innerSecondCallback').and.callFake(\n        function () {\n          orderOfCalls.push('innerSecond');\n        },\n      );\n    });\n\n    it('Should call function when node is attached', () => {\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n      render(<RefTester inner={false} innersecond={false} />, container);\n\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyPreviousSibling.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>abc</span>',\n      );\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n\n      render(<RefTester inner={true} innersecond={false} />, container);\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyInner.calls.argsFor(0)[0].outerHTML).toEqual('<div></div>');\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n\n      render(<RefTester inner={true} innersecond={true} />, container);\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>dfg</span>',\n      );\n    });\n\n    it('Should call ref functions in order: child to parent', () => {\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n\n      render(<RefTester inner={true} innersecond={true} />, container);\n\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      expect(spyPreviousSibling.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>abc</span>',\n      );\n      expect(spyInner.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<div><span>dfg</span></div>',\n      );\n      expect(spyInnerSecond.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>dfg</span>',\n      );\n\n      expect(orderOfCalls).toEqual([\n        'spyPreviousSibling',\n        'innerSecond',\n        'inner',\n      ]);\n    });\n\n    it('Should call ref when node is re-attached and re-unmounted', () => {\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n\n      render(<RefTester inner={true} innersecond={true} />, container);\n\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      expect(spyPreviousSibling.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>abc</span>',\n      );\n      expect(spyInner.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<div><span>dfg</span></div>',\n      );\n      expect(spyInnerSecond.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>dfg</span>',\n      );\n\n      expect(orderOfCalls).toEqual([\n        'spyPreviousSibling',\n        'innerSecond',\n        'inner',\n      ]);\n\n      // reset\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n\n      render(<RefTester inner={false} innersecond={true} />, container);\n\n      // Verify divs are removed from DOM\n      expect(container.innerHTML).toEqual('<div><span>abc</span></div>');\n\n      // Verify ref callbacks\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      expect(spyInner.calls.argsFor(0)[0]).toEqual(null);\n      expect(spyInnerSecond.calls.argsFor(0)[0]).toEqual(null);\n\n      // reset\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n\n      render(<RefTester inner={true} innersecond={true} />, container);\n\n      // Verify divs are attached\n      expect(container.innerHTML).toEqual(\n        '<div><span>abc</span><div><span>dfg</span></div></div>',\n      );\n\n      // Verify ref callbacks\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      expect(spyInner.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<div><span>dfg</span></div>',\n      );\n      expect(spyInnerSecond.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>dfg</span>',\n      );\n\n      // reset\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n    });\n\n    it('Should have width defined when html node is attached', () => {\n      if (global.usingJSDOM) {\n        // JSDOM mocks the ref node width to 0. Skip test\n        return;\n      }\n\n      let node: HTMLDivElement | null = null;\n\n      class Hello extends Component {\n        constructor(props) {\n          super(props);\n        }\n\n        public componentDidMount() {\n          expect(node!.offsetWidth).not.toEqual(0);\n        }\n\n        public ref(n) {\n          if (n) {\n            expect(n.offsetWidth).not.toEqual(0);\n            node = n;\n          }\n        }\n\n        public render() {\n          return <div ref={this.ref}>Hello World</div>;\n        }\n      }\n\n      render(<Hello />, container);\n    });\n  });\n\n  describe('ref hook complex', () => {\n    const fakeObj = {\n      previousSiblingCallback() {},\n      innerCallback() {},\n      innerSecondCallback() {},\n    };\n\n    const RefTester = ({ inner, innersecond }) => {\n      let content = null;\n      if (inner) {\n        let contentTwo = null;\n        if (innersecond) {\n          contentTwo = <span ref={fakeObj.innerSecondCallback}>dfg</span>;\n        }\n        content = <div ref={fakeObj.innerCallback}>{contentTwo}</div>;\n      }\n\n      return (\n        <div>\n          <span ref={fakeObj.previousSiblingCallback}>abc</span>\n          {content}\n        </div>\n      );\n    };\n\n    const PlainDiv = () => <div>plaindiv</div>;\n\n    const RefParent = ({ bool, inner, innersecond }) => {\n      return (\n        <div>\n          {bool ? (\n            <RefTester inner={inner} innersecond={innersecond} />\n          ) : (\n            <PlainDiv />\n          )}\n        </div>\n      );\n    };\n\n    let orderOfCalls: string[] = [];\n    let spyPreviousSibling = null as unknown as Spy;\n    let spyInner = null as unknown as Spy;\n    let spyInnerSecond = null as unknown as Spy;\n\n    beforeEach(function () {\n      orderOfCalls = [];\n      spyPreviousSibling = spyOn(\n        fakeObj,\n        'previousSiblingCallback',\n      ).and.callFake(function () {\n        orderOfCalls.push('spyPreviousSibling');\n      });\n      spyInner = spyOn(fakeObj, 'innerCallback').and.callFake(function () {\n        orderOfCalls.push('inner');\n      });\n      spyInnerSecond = spyOn(fakeObj, 'innerSecondCallback').and.callFake(\n        function () {\n          orderOfCalls.push('innerSecond');\n        },\n      );\n    });\n\n    afterEach(function () {\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n    });\n\n    it('Should not call ref unmount when node is not mounted', () => {\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n      render(\n        <RefParent bool={true} inner={false} innersecond={false} />,\n        container,\n      );\n\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyPreviousSibling.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>abc</span>',\n      );\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n\n      expect(container.innerHTML).toEqual(\n        '<div><div><span>abc</span></div></div>',\n      );\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n\n      // RENDER INNER DIVS\n      render(\n        <RefParent bool={true} inner={true} innersecond={true} />,\n        container,\n      );\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      // verify order\n      expect(orderOfCalls).toEqual([\n        'spyPreviousSibling',\n        'innerSecond',\n        'inner',\n      ]);\n\n      expect(spyInner.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<div><span>dfg</span></div>',\n      );\n      expect(spyInnerSecond.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>dfg</span>',\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div><span>abc</span><div><span>dfg</span></div></div></div>',\n      );\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n\n      // UNMOUNT INNER DIVS\n      render(\n        <RefParent bool={true} inner={false} innersecond={false} />,\n        container,\n      );\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      // verify order\n      expect(orderOfCalls).toEqual([\n        'spyPreviousSibling',\n        'innerSecond',\n        'inner',\n        'inner',\n        'innerSecond',\n      ]);\n\n      expect(spyInner.calls.argsFor(0)[0]).toEqual(null);\n      expect(spyInnerSecond.calls.argsFor(0)[0]).toEqual(null);\n\n      expect(container.innerHTML).toEqual(\n        '<div><div><span>abc</span></div></div>',\n      );\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n\n      // Inner and InnerSecond divs are now unmounted\n      // and unmounting parent should not cause them to unmounted again\n\n      // REPLACE PARENT\n      render(\n        <RefParent bool={false} inner={false} innersecond={false} />,\n        container,\n      );\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n      expect(container.innerHTML).toEqual('<div><div>plaindiv</div></div>');\n    });\n  });\n\n  describe('ref hook #2 with statefull components', () => {\n    const fakeObj = {\n      previousSiblingCallback() {},\n      innerCallback() {},\n      innerSecondCallback() {},\n    };\n\n    interface RefTesterProps {\n      inner?: boolean;\n      innersecond?: boolean;\n    }\n\n    class RefTester extends Component<RefTesterProps> {\n      public render() {\n        const inner = this.props.inner;\n        const innersecond = this.props.innersecond;\n\n        let content = null;\n        if (inner) {\n          let contentTwo = null;\n          if (innersecond) {\n            contentTwo = <span ref={fakeObj.innerSecondCallback}>dfg</span>;\n          }\n          content = <div ref={fakeObj.innerCallback}>{contentTwo}</div>;\n        }\n\n        return (\n          <div>\n            <span ref={fakeObj.previousSiblingCallback}>abc</span>\n            {content}\n          </div>\n        );\n      }\n    }\n\n    let orderOfCalls: string[] = [];\n    let spyPreviousSibling = null as unknown as Spy;\n    let spyInner = null as unknown as Spy;\n    let spyInnerSecond = null as unknown as Spy;\n\n    beforeEach(function () {\n      orderOfCalls = [];\n      spyPreviousSibling = spyOn(\n        fakeObj,\n        'previousSiblingCallback',\n      ).and.callFake(function () {\n        orderOfCalls.push('spyPreviousSibling');\n      });\n      spyInner = spyOn(fakeObj, 'innerCallback').and.callFake(function () {\n        orderOfCalls.push('inner');\n      });\n      spyInnerSecond = spyOn(fakeObj, 'innerSecondCallback').and.callFake(\n        function () {\n          orderOfCalls.push('innerSecond');\n        },\n      );\n    });\n\n    it('Should call function when node is attached #2', () => {\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n      render(<RefTester inner={false} innersecond={false} />, container);\n\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyPreviousSibling.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>abc</span>',\n      );\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n\n      render(<RefTester inner={true} innersecond={false} />, container);\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyInner.calls.argsFor(0)[0].outerHTML).toEqual('<div></div>');\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n\n      render(<RefTester inner={true} innersecond={true} />, container);\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>dfg</span>',\n      );\n    });\n\n    it('Should call ref functions in order: child to parent #2', () => {\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n\n      render(<RefTester inner={true} innersecond={true} />, container);\n\n      expect(spyPreviousSibling);\n      expect(spyInner);\n      expect(spyInnerSecond);\n      expect(spyPreviousSibling.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>abc</span>',\n      );\n      expect(spyInner.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<div><span>dfg</span></div>',\n      );\n      expect(spyInnerSecond.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>dfg</span>',\n      );\n\n      expect(orderOfCalls).toEqual([\n        'spyPreviousSibling',\n        'innerSecond',\n        'inner',\n      ]);\n    });\n\n    it('Should call ref when node is re-attached and re-unmounted', () => {\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n\n      render(<RefTester inner={true} innersecond={true} />, container);\n\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      expect(spyPreviousSibling.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>abc</span>',\n      );\n      expect(spyInner.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<div><span>dfg</span></div>',\n      );\n      expect(spyInnerSecond.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>dfg</span>',\n      );\n\n      expect(orderOfCalls).toEqual([\n        'spyPreviousSibling',\n        'innerSecond',\n        'inner',\n      ]);\n\n      // reset\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n\n      render(<RefTester inner={false} innersecond={true} />, container);\n\n      // Verify divs are removed from DOM\n      expect(container.innerHTML).toEqual('<div><span>abc</span></div>');\n\n      // Verify ref callbacks\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      expect(spyInner.calls.argsFor(0)[0]).toEqual(null);\n      expect(spyInnerSecond.calls.argsFor(0)[0]).toEqual(null);\n\n      // reset\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n\n      render(<RefTester inner={true} innersecond={true} />, container);\n\n      // Verify divs are attached\n      expect(container.innerHTML).toEqual(\n        '<div><span>abc</span><div><span>dfg</span></div></div>',\n      );\n\n      // Verify ref callbacks\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      expect(spyInner.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<div><span>dfg</span></div>',\n      );\n      expect(spyInnerSecond.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>dfg</span>',\n      );\n\n      // reset\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n    });\n  });\n\n  describe('ref hook complex #2 statefull components', () => {\n    const fakeObj = {\n      previousSiblingCallback() {},\n      innerCallback() {},\n      innerSecondCallback() {},\n    };\n\n    interface RefTesterProps {\n      bool?: boolean;\n      inner?: boolean;\n      innersecond?: boolean;\n    }\n\n    class RefTester extends Component<RefTesterProps> {\n      public render() {\n        const inner = this.props.inner;\n        const innersecond = this.props.innersecond;\n\n        let content = null;\n        if (inner) {\n          let contentTwo = null;\n          if (innersecond) {\n            contentTwo = <span ref={fakeObj.innerSecondCallback}>dfg</span>;\n          }\n          content = <div ref={fakeObj.innerCallback}>{contentTwo}</div>;\n        }\n\n        return (\n          <div>\n            <span ref={fakeObj.previousSiblingCallback}>abc</span>\n            {content}\n          </div>\n        );\n      }\n    }\n\n    class PlainDiv extends Component {\n      public render() {\n        return <div>plaindiv</div>;\n      }\n    }\n\n    interface RefParentProps {\n      bool?: boolean;\n      inner?: boolean;\n      innersecond?: boolean;\n    }\n\n    class RefParent extends Component<RefParentProps> {\n      public render() {\n        const { bool, inner, innersecond } = this.props;\n\n        return (\n          <div>\n            {bool ? (\n              <RefTester inner={inner} innersecond={innersecond} />\n            ) : (\n              <PlainDiv />\n            )}\n          </div>\n        );\n      }\n    }\n\n    let orderOfCalls: string[] = [];\n    let spyPreviousSibling = null as unknown as Spy;\n    let spyInner = null as unknown as Spy;\n    let spyInnerSecond = null as unknown as Spy;\n\n    beforeEach(function () {\n      orderOfCalls = [];\n      spyPreviousSibling = spyOn(\n        fakeObj,\n        'previousSiblingCallback',\n      ).and.callFake(function () {\n        orderOfCalls.push('spyPreviousSibling');\n      });\n      spyInner = spyOn(fakeObj, 'innerCallback').and.callFake(function () {\n        orderOfCalls.push('inner');\n      });\n      spyInnerSecond = spyOn(fakeObj, 'innerSecondCallback').and.callFake(\n        function () {\n          orderOfCalls.push('innerSecond');\n        },\n      );\n    });\n\n    afterEach(function () {\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n    });\n\n    it('Should not call ref unmount when node is not mounted #2', () => {\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n      render(\n        <RefParent bool={true} inner={false} innersecond={false} />,\n        container,\n      );\n\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyPreviousSibling.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>abc</span>',\n      );\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n\n      expect(container.innerHTML).toEqual(\n        '<div><div><span>abc</span></div></div>',\n      );\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n\n      // RENDER INNER DIVS\n      render(\n        <RefParent bool={true} inner={true} innersecond={true} />,\n        container,\n      );\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      // verify order\n      expect(orderOfCalls).toEqual([\n        'spyPreviousSibling',\n        'innerSecond',\n        'inner',\n      ]);\n\n      expect(spyInner.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<div><span>dfg</span></div>',\n      );\n      expect(spyInnerSecond.calls.argsFor(0)[0].outerHTML).toEqual(\n        '<span>dfg</span>',\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div><span>abc</span><div><span>dfg</span></div></div></div>',\n      );\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n\n      // UNMOUNT INNER DIVS\n      render(\n        <RefParent bool={true} inner={false} innersecond={false} />,\n        container,\n      );\n      expect(spyPreviousSibling).not.toHaveBeenCalled();\n      expect(spyInner).toHaveBeenCalledTimes(1);\n      expect(spyInnerSecond).toHaveBeenCalledTimes(1);\n      // verify order\n      expect(orderOfCalls).toEqual([\n        'spyPreviousSibling',\n        'innerSecond',\n        'inner',\n        'inner',\n        'innerSecond',\n      ]);\n\n      expect(spyInner.calls.argsFor(0)[0]).toEqual(null);\n      expect(spyInnerSecond.calls.argsFor(0)[0]).toEqual(null);\n\n      expect(container.innerHTML).toEqual(\n        '<div><div><span>abc</span></div></div>',\n      );\n      spyPreviousSibling.calls.reset();\n      spyInner.calls.reset();\n      spyInnerSecond.calls.reset();\n\n      // Inner and InnerSecond divs are now unmounted\n      // and unmounting parent should not cause them to unmounted again\n\n      // REPLACE PARENT\n      render(\n        <RefParent bool={false} inner={false} innersecond={false} />,\n        container,\n      );\n      expect(spyPreviousSibling).toHaveBeenCalledTimes(1);\n      expect(spyInner).not.toHaveBeenCalled();\n      expect(spyInnerSecond).not.toHaveBeenCalled();\n      expect(container.innerHTML).toEqual('<div><div>plaindiv</div></div>');\n    });\n  });\n\n  describe('ES6 Component within functional component', () => {\n    it('Should trigger lifecycle events when functional component change', () => {\n      let unmounted = false;\n\n      function A() {\n        return (\n          <div>\n            <Com />\n          </div>\n        );\n      }\n\n      function B() {\n        return (\n          <div>\n            <Com />\n          </div>\n        );\n      }\n\n      class Com extends Component {\n        public componentWillUnmount() {\n          unmounted = true;\n        }\n\n        public render() {\n          return <div>C</div>;\n        }\n      }\n\n      render(<A />, container);\n      expect(container.innerHTML).toEqual('<div><div>C</div></div>');\n      expect(unmounted).toEqual(false);\n      render(<B />, container);\n      expect(unmounted).toEqual(true);\n      expect(container.innerHTML).toEqual('<div><div>C</div></div>');\n    });\n\n    it('Should trigger lifecycle events when functional component dont change', () => {\n      let unmounted = false;\n\n      function A() {\n        return (\n          <div>\n            <Com />\n          </div>\n        );\n      }\n\n      class Com extends Component {\n        public componentWillUnmount() {\n          unmounted = true;\n        }\n\n        public render() {\n          return <div>C</div>;\n        }\n      }\n\n      render(<A />, container);\n      expect(container.innerHTML).toEqual('<div><div>C</div></div>');\n      expect(unmounted).toEqual(false);\n      render(<A />, container);\n      expect(unmounted).toEqual(false);\n      expect(container.innerHTML).toEqual('<div><div>C</div></div>');\n    });\n  });\n\n  describe('context with hooks', () => {\n    it('Should trigger componentWillMount before getting child context', () => {\n      interface AState {\n        foobar: string | null;\n      }\n\n      class A extends Component<unknown, AState> {\n        public state: AState;\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            foobar: null,\n          };\n        }\n\n        public getChildContext() {\n          return {\n            foobar: this.state.foobar,\n          };\n        }\n\n        public componentWillMount() {\n          this.setState({\n            foobar: 'hey',\n          });\n        }\n\n        public render() {\n          return (\n            <div>\n              <Child />\n            </div>\n          );\n        }\n      }\n\n      class Child extends Component {\n        constructor(props) {\n          super(props);\n        }\n\n        public render() {\n          return <span>{this.context.foobar}</span>;\n        }\n      }\n\n      render(<A />, container);\n\n      expect(container.innerHTML).toEqual('<div><span>hey</span></div>');\n    });\n  });\n\n  describe('ref', () => {\n    it('Should trigger lifecycle hooks when parent changes', () => {\n      const spy1 = jasmine.createSpy('spy');\n      const spy2 = jasmine.createSpy('spy');\n      const spy3 = jasmine.createSpy('spy');\n      const spy4 = jasmine.createSpy('spy');\n      const spy5 = jasmine.createSpy('spy');\n\n      class A extends Component {\n        public render() {\n          return (\n            <div>\n              <div ref={spy5}>\n                <span>1</span>\n                <span>1</span>\n              </div>\n            </div>\n          );\n        }\n      }\n\n      class B extends Component {\n        public componentWillMount() {\n          this.setState({\n            foo: 'bar',\n          });\n        }\n\n        public render() {\n          return (\n            <div>\n              <div ref={spy1} />\n              <Child />\n              <div />\n              <div ref={spy2} />\n              <div />\n              <Child ref={spy3} />\n            </div>\n          );\n        }\n      }\n\n      class Child extends Component {\n        public componentWillMount() {\n          this.setState({\n            foo: '1',\n          });\n        }\n\n        public render() {\n          return <div ref={spy4}>5</div>;\n        }\n      }\n\n      render(<A />, container);\n      expect(spy5.calls.count()).toBe(1);\n\n      render(<B />, container);\n\n      expect(spy5.calls.count()).toBe(2); // mount + unmount\n\n      expect(spy1.calls.count()).toBe(1);\n      expect(spy2.calls.count()).toBe(1);\n      expect(spy3.calls.count()).toBe(1);\n      expect(spy4.calls.count()).toBe(2); // 2 refs\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/input.spec.tsx",
    "content": "import { render } from 'inferno';\nimport { triggerEvent } from 'inferno-utils';\n\ndescribe('Input type checkbox', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Checked attribute should be false', function () {\n    render(<input type=\"checkbox\" checked={false} />, container);\n    const input = container.firstChild;\n\n    expect(input.checked).toBe(false);\n  });\n\n  it('Checked attribute after Click', function () {\n    let clickChecked: boolean | null = null;\n    let changeChecked: boolean | null = null;\n\n    render(\n      <input\n        type=\"checkbox\"\n        checked={false}\n        onclick={(e) => {\n          clickChecked = e.currentTarget.checked;\n        }}\n        onChange={(e) => {\n          changeChecked = e.currentTarget.checked;\n        }}\n      />,\n      container,\n    );\n    const input = container.firstChild;\n\n    triggerEvent('click', input);\n\n    expect(input.checked).toBe(false);\n    expect(clickChecked).toBe(true);\n    expect(changeChecked).toBe(true);\n  });\n\n  it('Checkbox click should not propagate to parent', function () {\n    let clickChecked: boolean | null = null;\n    let changeChecked: boolean | null = null;\n    let parentClick = false;\n\n    render(\n      <div onClick={() => (parentClick = true)}>\n        <input\n          type=\"checkbox\"\n          checked={false}\n          onclick={(e) => {\n            clickChecked = e.currentTarget.checked;\n          }}\n          onChange={(e) => {\n            changeChecked = e.currentTarget.checked;\n          }}\n        />\n      </div>,\n      container,\n    );\n    const input = container.querySelector('input');\n\n    expect(parentClick).toBe(false);\n\n    triggerEvent('click', input);\n\n    expect(input.checked).toBe(false);\n    expect(clickChecked).toBe(true);\n    expect(changeChecked).toBe(true);\n    expect(parentClick).toBe(false);\n  });\n\n  it('Checked attribute after synthetic Click', function () {\n    let nClicks = 0;\n    let clickChecked: boolean | null = null;\n    let nChanges = 0;\n    let changeChecked: boolean | null = null;\n\n    render(\n      <input\n        type=\"checkbox\"\n        checked={false}\n        onClick={(e) => {\n          clickChecked = e.currentTarget.checked;\n          nClicks++;\n        }}\n        onChange={(e) => {\n          changeChecked = e.currentTarget.checked;\n          nChanges++;\n        }}\n      />,\n      container,\n    );\n    const input = container.firstChild;\n\n    triggerEvent('click', input);\n\n    expect(input.checked).toBe(false);\n    expect(nClicks).toBe(1);\n    expect(clickChecked).toBe(true);\n    expect(nChanges).toBe(1);\n    expect(changeChecked).toBe(true);\n  });\n});\n\ndescribe('Input type Radio', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Controlled radio, checked=false', function () {\n    render(<input type=\"radio\" checked={false} value=\"magic\" />, container);\n    const input = container.firstChild;\n\n    expect(input.checked).toBe(false);\n  });\n\n  it('Checked attribute after Click #2', function () {\n    let clickChecked: boolean | null = null;\n    let changeChecked: boolean | null = null;\n\n    render(\n      <input\n        type=\"radio\"\n        checked={false}\n        value=\"magic\"\n        onclick={(e) => {\n          clickChecked = e.currentTarget.checked;\n        }}\n        onChange={(e) => {\n          changeChecked = e.currentTarget.checked;\n        }}\n      />,\n      container,\n    );\n    const input = container.firstChild;\n\n    triggerEvent('click', input);\n\n    expect(clickChecked).toBe(true);\n    expect(input.checked).toBe(false);\n    expect(changeChecked).toBe(true);\n  });\n\n  it('Checked attribute after synthetic Click #3', function () {\n    let clickChecked: boolean | null = null;\n    let changeChecked: boolean | null = null;\n\n    render(\n      <input\n        type=\"radio\"\n        checked={false}\n        value=\"magic\"\n        onClick={(e) => {\n          clickChecked = e.currentTarget.checked;\n        }}\n        onChange={(e) => {\n          changeChecked = e.currentTarget.checked;\n        }}\n      />,\n      container,\n    );\n    const input = container.firstChild;\n\n    triggerEvent('click', input);\n\n    expect(clickChecked).toBe(true);\n    expect(input.checked).toBe(false);\n    expect(changeChecked).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/instancenull.spec.tsx",
    "content": "import { Component, type InfernoNode, render, rerender } from 'inferno';\nimport { triggerEvent } from 'inferno-utils';\n\ndescribe('BUG: instance - null', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  const Triangle = ({ direction }) => (\n    <svg className={`popover-triangle ${direction}`}>\n      <polygon points={'0,0'} />\n    </svg>\n  );\n\n  function DropdownItem({ className, children, attached }) {\n    return (\n      <li ref={attached} className={`dd-item ${className}`}>\n        {children}\n      </li>\n    );\n  }\n\n  interface IconProps {\n    icon?: string;\n  }\n\n  class Icon extends Component<IconProps> {\n    constructor(props, context) {\n      super(props, context);\n    }\n\n    public componentWillMount() {}\n\n    public render() {\n      const props = this.props;\n\n      if (!props.icon) {\n        return null;\n      }\n\n      /*\n       * FireFox v51.0 fixes issue with href\n       * iOS still broken (21.1.2017)\n       */\n\n      return (\n        <svg focusable=\"false\" className={'svgicon'}>\n          <use xlink:href={props.icon} />\n        </svg>\n      );\n    }\n  }\n\n  interface PopoverProps {\n    popoverClassName?: string;\n    align?: string;\n    arrow?: boolean;\n    isOpen?: boolean;\n    target?: HTMLDivElement | null;\n    hasMobileClose?: boolean;\n    body?: InfernoNode;\n    onOuterAction?: (ev: any) => void;\n  }\n\n  interface PopoverState {\n    placement: string;\n  }\n\n  class Popover extends Component<PopoverProps, PopoverState> {\n    private readonly _elements: {\n      container: HTMLDivElement | null;\n      parentPopover: HTMLDivElement | null;\n      popover: HTMLDivElement | null;\n      target: HTMLDivElement | null;\n      popoverBody: HTMLDivElement | null;\n    };\n\n    public state: PopoverState;\n\n    constructor(props) {\n      super(props);\n\n      this.state = {\n        placement: 'below',\n      };\n\n      // Element references\n      this._elements = {\n        container: null,\n        parentPopover: null,\n        popover: null,\n        popoverBody: null,\n        target: props.target || null,\n      };\n\n      // Lexical bindings\n      this._refContainer = this._refContainer.bind(this);\n      this._refTarget = this._refTarget.bind(this);\n      this._refPopoverBody = this._refPopoverBody.bind(this);\n      this._popoverRef = this._popoverRef.bind(this);\n    }\n\n    //\n    // PRIVATE GETTER\n    //\n\n    //\n    // Private\n    //\n\n    public _popoverRef(node) {\n      this._elements.popover = node;\n      if (node !== null) {\n        this.setState({\n          placement: '',\n        });\n      }\n    }\n\n    public _refContainer(node) {\n      this._elements.container = node;\n    }\n\n    public _refPopoverBody(node) {\n      this._elements.popoverBody = node;\n    }\n\n    public _refTarget(node) {\n      if (!this.props.target) {\n        this._elements.target = node;\n      }\n    }\n\n    //\n    // PRIVATE STATIC\n    //\n\n    //\n    // OVERRIDEN FROM COMPONENT\n    //\n    public render() {\n      const props = this.props;\n      let popover = null;\n      let closeButton = null;\n\n      if (props.isOpen) {\n        let triangle = null;\n\n        if (props.arrow !== false) {\n          triangle = <Triangle direction={this.state.placement} />;\n        }\n\n        popover = (\n          <div ref={this._popoverRef} className=\"popover\">\n            <div className=\"popover-layer\">\n              {triangle}\n              <div ref={this._refPopoverBody} className=\"popover-body\">\n                {props.body}\n              </div>\n            </div>\n          </div>\n        );\n      }\n\n      if (props.hasMobileClose) {\n        closeButton = (\n          <div\n            className=\"inverse-action popover-close\"\n            onClick={props.onOuterAction}\n          />\n        );\n      }\n\n      return (\n        <div ref={this._refContainer} className=\"popover-placeholder\">\n          {closeButton}\n          <div className=\"popover-target\" ref={this._refTarget}>\n            {props.children}\n          </div>\n          {popover}\n        </div>\n      );\n    }\n  }\n\n  interface DropdownProps {\n    items: Array<{\n      icon: string;\n      text: string;\n      value: string;\n    }>;\n\n    changeCallback?: () => void;\n    changeParams?: unknown;\n    value?: string;\n  }\n\n  interface DropdownState {\n    activeValue?: string | null;\n    editableText: string;\n    isEditMode: boolean;\n    filteredItems: Array<{\n      icon: string;\n      text: string;\n      value: string;\n    }> | null;\n  }\n\n  class Dropdown extends Component<DropdownProps, DropdownState> {\n    private readonly _elements: {\n      bottomLoader: null;\n      activeNode: null;\n      list: null;\n    };\n\n    // @ts-expect-error\n    private _popover: HTMLDivElement | null;\n\n    public state: DropdownState;\n\n    constructor(props) {\n      super(props);\n\n      // Element references\n      this._elements = {\n        activeNode: null,\n        bottomLoader: null,\n        list: null,\n      };\n\n      this.state = {\n        activeValue: props.value,\n        editableText: '',\n        filteredItems: null,\n        isEditMode: false,\n      };\n\n      // Lexical bindings\n      this._closePopover = this._closePopover.bind(this);\n      this._onActiveItemAttached = this._onActiveItemAttached.bind(this);\n      this._onDropDownCreating = this._onDropDownCreating.bind(this);\n      this._refPopover = this._refPopover.bind(this);\n      this._refBottomLoader = this._refBottomLoader.bind(this);\n      this._makeEditable = this._makeEditable.bind(this);\n    }\n\n    //\n    // PRIVATE\n    //\n\n    // In some cases, we don't want to stop event propagation, f.e. listView editMode and movements with shift + TAB\n    public _closePopover(event) {\n      event.stopPropagation();\n\n      this.setState({\n        activeValue: this.props.value,\n        editableText: '',\n        filteredItems: null,\n        isEditMode: false,\n      });\n    }\n\n    public _onDropDownCreating(node) {\n      this._elements.list = node;\n    }\n\n    public _onActiveItemAttached(node) {\n      this._elements.activeNode = node;\n    }\n\n    public _refPopover(instance) {\n      this._popover = instance;\n    }\n\n    public _refBottomLoader(node) {\n      this._elements.bottomLoader = node;\n    }\n\n    public _renderItems() {\n      const items = this.state.filteredItems || this.props.items || [];\n      const itemsToRender: InfernoNode[] = [];\n\n      for (let i = 0; i < items.length; i++) {\n        const item = items[i];\n\n        itemsToRender.push(this._renderItem(item, i));\n      }\n\n      return itemsToRender;\n    }\n\n    public _renderDropdown() {\n      const currentState = this.state;\n\n      // Shortcut dropdown rendering process when its not visible\n      if (!currentState.isEditMode) {\n        return null;\n      }\n\n      // Render items\n      const items = this._renderItems();\n\n      return (\n        <ul className=\"editable-dropdown\" ref={this._onDropDownCreating}>\n          {items}\n        </ul>\n      );\n    }\n\n    public _renderItem(dropdownItem, isActive) {\n      return (\n        <DropdownItem\n          attached={isActive ? this._onActiveItemAttached : null}\n          key={dropdownItem.value}\n          className={'dd-item-icon'}\n        >\n          <Icon icon={dropdownItem.icon} />\n          {dropdownItem.text}\n        </DropdownItem>\n      );\n    }\n\n    public _makeEditable() {\n      const state = this.state;\n      const props = this.props;\n\n      if (state.isEditMode) {\n        return;\n      }\n\n      // Updating editable and changing into editmode\n      this.setState({\n        activeValue: props.value,\n        isEditMode: true,\n      });\n    }\n\n    //\n    // OVERRIDDEN FROM COMPONENT\n    //\n\n    public render() {\n      return (\n        <Popover\n          ref={this._refPopover}\n          arrow={true}\n          align=\"begin\"\n          hasMobileClose={true}\n          isOpen={this.state.isEditMode}\n          body={this._renderDropdown()}\n          onOuterAction={this._closePopover}\n        >\n          <div\n            id=\"MAGICBUTTON\"\n            onclick={\n              this.state.isEditMode ? this._closePopover : this._makeEditable\n            }\n          >\n            TEST\n          </div>\n        </Popover>\n      );\n    }\n  }\n\n  it('Should not fail', () => {\n    const items = [\n      {\n        icon: '#user',\n        text: 'Implementation',\n        value: 'b73ea78d-350d-f764-e429-9bebd9d8b4b3',\n      },\n      {\n        icon: '#reminder',\n        text: 'Issue',\n        value: '4e0a069d-899a-418a-df27-8ff5ef18d459',\n      },\n      {\n        icon: '#favourite',\n        text: 'LomaTaski',\n        value: 'd9a54cc9-2a16-08e3-85da-c230b5d0b121',\n      },\n    ];\n    const value = 'b73ea78d-350d-f764-e429-9bebd9d8b4b3';\n\n    render(\n      <div>\n        <Dropdown\n          items={items}\n          changeCallback={function () {}}\n          changeParams={{ guid: 'foo', field: 'activityType' }}\n          value={value}\n        />\n      </div>,\n      container,\n    );\n\n    triggerEvent('click', container.querySelector('#MAGICBUTTON'));\n\n    rerender();\n    expect(container.querySelectorAll('.dd-item').length).toBe(3);\n\n    triggerEvent('click', container.querySelector('#MAGICBUTTON'));\n\n    rerender();\n    expect(container.querySelectorAll('.dd-item').length).toBe(0);\n\n    rerender();\n    triggerEvent('click', container.querySelector('#MAGICBUTTON'));\n\n    expect(container.querySelectorAll('.dd-item').length).toBe(3);\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should not fail #2', () => {\n    const items = [\n      {\n        icon: '#user',\n        text: 'Implementation',\n        value: 'b73ea78d-350d-f764-e429-9bebd9d8b4b3',\n      },\n      {\n        icon: '#reminder',\n        text: 'Issue',\n        value: '4e0a069d-899a-418a-df27-8ff5ef18d459',\n      },\n      {\n        icon: '#favourite',\n        text: 'LomaTaski',\n        value: 'd9a54cc9-2a16-08e3-85da-c230b5d0b121',\n      },\n    ];\n    const value = 'b73ea78d-350d-f764-e429-9bebd9d8b4b3';\n\n    render(\n      <div>\n        <Dropdown\n          items={items}\n          changeCallback={function () {}}\n          changeParams={{ guid: 'foo', field: 'activityType' }}\n          value={value}\n        />\n      </div>,\n      container,\n    );\n\n    container.querySelector('#MAGICBUTTON').click();\n\n    render(\n      <div>\n        <Icon />\n      </div>,\n      container,\n    );\n  });\n\n  it('Should not fail #3', () => {\n    const items = [\n      {\n        icon: '#user',\n        text: 'Implementation',\n        value: 'b73ea78d-350d-f764-e429-9bebd9d8b4b3',\n      },\n      {\n        icon: '#reminder',\n        text: 'Issue',\n        value: '4e0a069d-899a-418a-df27-8ff5ef18d459',\n      },\n      {\n        icon: '#favourite',\n        text: 'LomaTaski',\n        value: 'd9a54cc9-2a16-08e3-85da-c230b5d0b121',\n      },\n    ];\n    const value = 'b73ea78d-350d-f764-e429-9bebd9d8b4b3';\n\n    render(\n      <div>\n        <Dropdown\n          items={items}\n          changeCallback={function () {}}\n          changeParams={{ guid: 'foo', field: 'activityType' }}\n          value={value}\n        />\n      </div>,\n      container,\n    );\n\n    container.querySelector('#MAGICBUTTON').click();\n\n    render(\n      <div>\n        <Dropdown\n          items={items}\n          changeCallback={function () {}}\n          changeParams={{ guid: 'dwqwdq', field: 'activityType' }}\n          value={value}\n        />\n      </div>,\n      container,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/issue-1369.spec.tsx",
    "content": "import { Component, render } from 'inferno';\n\ndescribe('static tree as child nodes', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should patch whole tree even when static - Github #1369', () => {\n    let renderCounter = 0;\n\n    class Form extends Component {\n      public handleClick = () => {\n        this.forceUpdate();\n      };\n\n      public static childContextTypes = {};\n\n      public getChildContext() {\n        return {};\n      }\n\n      public render() {\n        const { children, ...restProps } = this.props;\n        return (\n          <div {...restProps}>\n            <button onClick={this.handleClick}>test</button>\n            {children}\n          </div>\n        );\n      }\n    }\n\n    class Test extends Component {\n      public render() {\n        renderCounter++;\n\n        return <div>test</div>;\n      }\n    }\n\n    class App extends Component {\n      public render() {\n        return (\n          <Form>\n            <div>\n              <div>\n                <Test />\n              </div>\n            </div>\n          </Form>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    expect(renderCounter).toBe(1);\n\n    const btn = container.querySelector('button');\n\n    btn.click();\n\n    expect(renderCounter).toBe(2);\n\n    btn.click();\n\n    expect(renderCounter).toBe(3);\n\n    btn.click();\n\n    expect(renderCounter).toBe(4);\n\n    btn.click();\n\n    expect(renderCounter).toBe(5);\n  });\n\n  it('Should patch whole tree even when static - Github #1369 - 2', () => {\n    let renderCounter = 0;\n\n    class Form extends Component {\n      public handleClick = () => {\n        this.forceUpdate();\n      };\n\n      public static childContextTypes = {};\n\n      public getChildContext() {\n        return {};\n      }\n\n      public render() {\n        const { children } = this.props;\n        return (\n          <div>\n            <button onClick={this.handleClick}>test</button>\n            {children}\n          </div>\n        );\n      }\n    }\n\n    let constuctCounter = 0;\n\n    interface TestState {\n      text: string;\n    }\n\n    class Test extends Component<unknown, TestState> {\n      public state: TestState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          text: 'bar',\n        };\n\n        constuctCounter++;\n      }\n\n      public render() {\n        renderCounter++;\n\n        return (\n          <div\n            id={`id-${renderCounter}`}\n            onClick={() => {\n              this.setState({ text: 'foo' });\n            }}\n            $HasTextChildren\n          >\n            {this.state.text}\n          </div>\n        );\n      }\n    }\n\n    class App extends Component {\n      public render() {\n        const hoistedDiv = (\n          <div>\n            <Test />\n          </div>\n        );\n\n        return (\n          <Form>\n            <div>\n              <div>{hoistedDiv}</div>\n              <div>{hoistedDiv}</div>\n              <div>{hoistedDiv}</div>\n            </div>\n          </Form>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    expect(renderCounter).toBe(3);\n    expect(constuctCounter).toBe(3);\n\n    const expectedHTML = `<div><button>test</button><div><div><div><div id=\"id-1\">bar</div></div></div><div><div><div id=\"id-2\">bar</div></div></div><div><div><div id=\"id-3\">bar</div></div></div></div></div>`;\n\n    expect(container.innerHTML).toBe(expectedHTML);\n\n    const btn = container.querySelector('button');\n\n    btn.click();\n\n    expect(renderCounter).toBe(6);\n    expect(constuctCounter).toBe(3);\n\n    expect(container.innerHTML).toBe(\n      `<div><button>test</button><div><div><div><div id=\"id-4\">bar</div></div></div><div><div><div id=\"id-5\">bar</div></div></div><div><div><div id=\"id-6\">bar</div></div></div></div></div>`,\n    );\n\n    container.querySelector('#id-4').click();\n\n    expect(renderCounter).toBe(7);\n    expect(constuctCounter).toBe(3);\n\n    expect(container.innerHTML).toBe(\n      `<div><button>test</button><div><div><div><div id=\"id-7\">foo</div></div></div><div><div><div id=\"id-5\">bar</div></div></div><div><div><div id=\"id-6\">bar</div></div></div></div></div>`,\n    );\n\n    container.querySelector('#id-5').click();\n\n    expect(renderCounter).toBe(8);\n    expect(constuctCounter).toBe(3);\n\n    expect(container.innerHTML).toBe(\n      `<div><button>test</button><div><div><div><div id=\"id-7\">foo</div></div></div><div><div><div id=\"id-8\">foo</div></div></div><div><div><div id=\"id-6\">bar</div></div></div></div></div>`,\n    );\n\n    container.querySelector('#id-6').click();\n\n    expect(renderCounter).toBe(9);\n    expect(constuctCounter).toBe(3);\n\n    expect(container.innerHTML).toBe(\n      `<div><button>test</button><div><div><div><div id=\"id-7\">foo</div></div></div><div><div><div id=\"id-8\">foo</div></div></div><div><div><div id=\"id-9\">foo</div></div></div></div></div>`,\n    );\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/lifecycle.spec.tsx",
    "content": "import { Component, render, rerender } from 'inferno';\n\ndescribe('ComponentDidUpdate', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should be called after ref updates, Github #1374 Github#1286', () => {\n    class App extends Component {\n      public state = {\n        toggled: false,\n      };\n\n      private dynamicEl: HTMLDivElement | null;\n      private staticEl: HTMLDivElement | null;\n\n      public toggleDynamicComponent = () => {\n        this.setState({\n          toggled: !this.state.toggled,\n        });\n      };\n\n      public renderDynamicComponent = () => (\n        <div\n          id=\"dynamic\"\n          ref={(el) => {\n            this.dynamicEl = el;\n          }}\n        >\n          <p>Dynamic component!</p>\n        </div>\n      );\n\n      public componentDidUpdate() {\n        const dynamic = container.querySelector('#dynamic');\n\n        expect(this.dynamicEl).toBe(dynamic);\n        if (this.state.toggled) {\n          expect(dynamic).not.toBeNull();\n        } else {\n          expect(dynamic).toBeNull();\n        }\n\n        expect(this.staticEl).toBe(container.querySelector('#static'));\n      }\n\n      public render() {\n        return (\n          <div\n            id=\"static\"\n            ref={(el) => {\n              this.staticEl = el;\n            }}\n          >\n            {this.state.toggled && this.renderDynamicComponent()}\n            <button onClick={this.toggleDynamicComponent}>\n              Toggle dynamic component\n            </button>\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    const button = container.querySelector('button');\n\n    button.click();\n    button.click();\n    button.click();\n    button.click();\n  });\n\n  it('Should unmount refs parent first', () => {\n    const spyer = jasmine.createSpy();\n\n    class Mounter extends Component {\n      public componentDidMount() {\n        spyer('child-didmount');\n      }\n\n      public componentWillUnmount() {\n        spyer('child-willunmount');\n      }\n    }\n\n    interface AppProps {\n      child?: boolean;\n    }\n\n    class App extends Component<AppProps> {\n      public componentDidMount() {\n        spyer('parent-didmount');\n      }\n\n      public componentWillUnmount() {\n        spyer('parent-willunmount');\n      }\n\n      public render() {\n        return (\n          <div\n            id=\"outer\"\n            ref={(el) => {\n              // Create new function on purpose to trigger changes\n              spyer('outer-' + (el ? el.id : null));\n            }}\n          >\n            <div\n              id=\"inner\"\n              ref={(el) => {\n                // Create new function on purpose to trigger changes\n                spyer('inner-' + (el ? el.id : null));\n              }}\n            >\n              {this.props.child ? <Mounter /> : null}\n            </div>\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    expect(spyer).toHaveBeenCalledTimes(3);\n    expect(spyer.calls.argsFor(0)).toEqual(['inner-inner']);\n    expect(spyer.calls.argsFor(1)).toEqual(['outer-outer']);\n    expect(spyer.calls.argsFor(2)).toEqual(['parent-didmount']);\n\n    render(<App child={true} />, container);\n\n    expect(spyer.calls.argsFor(3)).toEqual(['inner-null']);\n    expect(spyer.calls.argsFor(4)).toEqual(['outer-null']);\n    expect(spyer.calls.argsFor(5)).toEqual(['child-didmount']);\n    expect(spyer.calls.argsFor(6)).toEqual(['inner-inner']);\n    expect(spyer.calls.argsFor(7)).toEqual(['outer-outer']);\n\n    expect(spyer).toHaveBeenCalledTimes(8);\n\n    render(<App child={false} />, container);\n\n    expect(spyer.calls.argsFor(8)).toEqual(['child-willunmount']);\n    expect(spyer.calls.argsFor(9)).toEqual(['inner-null']);\n    expect(spyer.calls.argsFor(10)).toEqual(['outer-null']);\n    expect(spyer.calls.argsFor(11)).toEqual(['inner-inner']);\n    expect(spyer.calls.argsFor(12)).toEqual(['outer-outer']);\n\n    expect(spyer).toHaveBeenCalledTimes(13);\n\n    render(<App child={true} />, container);\n\n    expect(spyer.calls.argsFor(13)).toEqual(['inner-null']);\n    expect(spyer.calls.argsFor(14)).toEqual(['outer-null']);\n    expect(spyer.calls.argsFor(15)).toEqual(['child-didmount']);\n    expect(spyer.calls.argsFor(16)).toEqual(['inner-inner']);\n    expect(spyer.calls.argsFor(17)).toEqual(['outer-outer']);\n\n    expect(spyer).toHaveBeenCalledTimes(18);\n\n    render(null, container);\n\n    expect(spyer.calls.argsFor(18)).toEqual(['parent-willunmount']);\n    expect(spyer.calls.argsFor(19)).toEqual(['outer-null']);\n    expect(spyer.calls.argsFor(20)).toEqual(['inner-null']);\n    expect(spyer.calls.argsFor(21)).toEqual(['child-willunmount']);\n\n    expect(spyer).toHaveBeenCalledTimes(22);\n  });\n\n  // https://jsfiddle.net/3ja27qw5/\n  it('Should unmount refs parent first - variation 2', () => {\n    const spyer = jasmine.createSpy();\n\n    class Mounter extends Component {\n      public componentDidMount() {\n        spyer('child-didmount');\n      }\n\n      public componentWillUnmount() {\n        spyer('child-willunmount');\n      }\n    }\n\n    interface AppProps {\n      child?: boolean;\n    }\n\n    class App extends Component<AppProps> {\n      public componentDidMount() {\n        spyer('parent-didmount');\n      }\n\n      public componentWillUnmount() {\n        spyer('parent-willunmount');\n      }\n\n      public render() {\n        return (\n          <div\n            id=\"outer\"\n            ref={(el) => {\n              // Create new function on purpose to trigger changes\n              spyer('outer-' + (el ? el.id : null));\n            }}\n          >\n            <Mounter />\n            <div\n              id=\"inner\"\n              ref={(el) => {\n                // Create new function on purpose to trigger changes\n                spyer('inner-' + (el ? el.id : null));\n              }}\n            >\n              {this.props.child ? <Mounter /> : null}\n            </div>\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    expect(spyer).toHaveBeenCalledTimes(4);\n    expect(spyer.calls.argsFor(0)).toEqual(['child-didmount']);\n    expect(spyer.calls.argsFor(1)).toEqual(['inner-inner']);\n    expect(spyer.calls.argsFor(2)).toEqual(['outer-outer']);\n    expect(spyer.calls.argsFor(3)).toEqual(['parent-didmount']);\n\n    render(<App child={true} />, container);\n\n    expect(spyer.calls.argsFor(4)).toEqual(['inner-null']);\n    expect(spyer.calls.argsFor(5)).toEqual(['outer-null']);\n    expect(spyer.calls.argsFor(6)).toEqual(['child-didmount']);\n    expect(spyer.calls.argsFor(7)).toEqual(['inner-inner']);\n    expect(spyer.calls.argsFor(8)).toEqual(['outer-outer']);\n\n    render(null, container);\n\n    expect(spyer.calls.argsFor(9)).toEqual(['parent-willunmount']);\n    expect(spyer.calls.argsFor(10)).toEqual(['outer-null']);\n    expect(spyer.calls.argsFor(11)).toEqual(['child-willunmount']);\n    expect(spyer.calls.argsFor(12)).toEqual(['inner-null']);\n    expect(spyer.calls.argsFor(13)).toEqual(['child-willunmount']);\n\n    expect(spyer).toHaveBeenCalledTimes(14);\n  });\n\n  it('Should not call setState callback if another component triggers setState during other tree mount', () => {\n    // This is only to simplify whats going on in real application\n    const testHack = {\n      callback: () => {},\n    };\n\n    let callbackCalled = 0;\n    let setState1Called = 0;\n    let setState2Called = 0;\n\n    class Another extends Component {\n      constructor(props, context) {\n        super(props, context);\n\n        testHack.callback = () => {\n          callbackCalled++;\n          this.setState({ a: 112 });\n        };\n      }\n\n      public render() {\n        return <div>A</div>;\n      }\n    }\n\n    class TesterOne extends Component {\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          foo: 'test',\n        };\n      }\n\n      public componentWillMount() {\n        this.setState(\n          {\n            foo: 'bar',\n          },\n          function () {\n            setState1Called++;\n            expect(this.state.foo).toBe('bar');\n          },\n        );\n\n        testHack.callback();\n      }\n\n      public render() {\n        return <div>Tester One</div>;\n      }\n    }\n\n    interface OutsiderState {\n      bool?: boolean;\n    }\n\n    class Outsider extends Component<unknown, OutsiderState> {\n      public state: OutsiderState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          bool: false,\n        };\n\n        this._handleClick = this._handleClick.bind(this);\n      }\n\n      public _handleClick() {\n        this.setState(\n          {\n            bool: true,\n          },\n          function () {\n            setState2Called++;\n            expect(this.state.bool).toBe(true);\n          },\n        );\n      }\n\n      public render() {\n        return (\n          <div id=\"tester\" onClick={this._handleClick}>\n            {this.state.bool ? <TesterOne /> : <span />}\n          </div>\n        );\n      }\n    }\n\n    class App extends Component {\n      public render() {\n        return (\n          <div>\n            <Outsider />\n            <Another />\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    expect(callbackCalled).toBe(0);\n    expect(setState1Called).toBe(0);\n    expect(setState2Called).toBe(0);\n\n    expect(container.innerHTML).toBe(\n      '<div><div id=\"tester\"><span></span></div><div>A</div></div>',\n    );\n\n    container.querySelector('#tester').click();\n\n    expect(callbackCalled).toBe(1);\n    expect(setState1Called).toBe(1);\n    expect(setState2Called).toBe(1);\n\n    expect(container.innerHTML).toBe(\n      '<div><div id=\"tester\"><div>Tester One</div></div><div>A</div></div>',\n    );\n  });\n\n  it('Should not fail if mounting subtree propagates callback to parent which renders again', () => {\n    // This is only to simplify whats going on in real application\n    const testHack = {\n      callback: () => {},\n    };\n\n    let callbackCalled = 0;\n    let setState1Called = 0;\n    let setState2Called = 0;\n    let mounterCounter = 0;\n\n    interface AnotherProps {\n      a: number;\n    }\n\n    class Another extends Component<AnotherProps> {\n      public render() {\n        return <div>A {this.props.a}</div>;\n      }\n    }\n\n    interface TesterOneProps {\n      a: number;\n    }\n\n    class TesterOne extends Component<TesterOneProps> {\n      constructor(props) {\n        super(props);\n\n        mounterCounter++;\n\n        this.state = {\n          foo: 'test',\n        };\n      }\n\n      public componentWillMount() {\n        this.setState(\n          {\n            foo: 'bar',\n          },\n          function () {\n            setState1Called++;\n            expect(this.state.foo).toBe('bar');\n          },\n        );\n\n        testHack.callback();\n      }\n\n      public render() {\n        return <div>Tester One {this.props.a}</div>;\n      }\n    }\n\n    interface OutsiderState {\n      bool?: boolean;\n    }\n\n    interface OutsiderProps {\n      a: number;\n    }\n\n    class Outsider extends Component<OutsiderProps, OutsiderState> {\n      public state: OutsiderState;\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          bool: false,\n        };\n\n        this._handleClick = this._handleClick.bind(this);\n      }\n\n      public _handleClick() {\n        this.setState(\n          {\n            bool: true,\n          },\n          function () {\n            setState2Called++;\n            expect(this.state.bool).toBe(true);\n          },\n        );\n      }\n\n      public render() {\n        return (\n          <div id=\"tester\" onClick={this._handleClick}>\n            {this.state.bool ? (\n              <TesterOne a={this.props.a} />\n            ) : (\n              <span>{this.props.a}</span>\n            )}\n          </div>\n        );\n      }\n    }\n\n    interface AppState {\n      a: number;\n    }\n\n    class App extends Component<unknown, AppState> {\n      public state: AppState;\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          a: 0,\n        };\n\n        testHack.callback = () => {\n          callbackCalled++;\n          this.setState({ a: 112 });\n        };\n      }\n\n      public render() {\n        return (\n          <div>\n            <Outsider a={this.state.a} />\n            <Another a={this.state.a} />\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    expect(mounterCounter).toBe(0);\n    expect(callbackCalled).toBe(0);\n    expect(setState1Called).toBe(0);\n    expect(setState2Called).toBe(0);\n\n    expect(container.innerHTML).toBe(\n      '<div><div id=\"tester\"><span>0</span></div><div>A 0</div></div>',\n    );\n\n    container.querySelector('#tester').click();\n\n    rerender();\n\n    expect(mounterCounter).toBe(1);\n    expect(callbackCalled).toBe(1);\n    expect(setState1Called).toBe(1);\n    expect(setState2Called).toBe(1);\n\n    expect(container.innerHTML).toBe(\n      '<div><div id=\"tester\"><div>Tester One 112</div></div><div>A 112</div></div>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/link.spec.tsx",
    "content": "import { render } from 'inferno';\n\ndescribe('Links', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('javascript href', function () {\n    it('Should log warning when rendering link starting with javascript::', function () {\n      const consoleSpy = spyOn(console, 'error');\n\n      render(<a href=\"javascript:foobar\">test</a>, container);\n\n      expect(consoleSpy).toHaveBeenCalledTimes(1);\n      expect(consoleSpy).toHaveBeenCalledWith(\n        'Rendering links with javascript: URLs is not recommended. Use event handlers instead if you can. Inferno was passed \"javascript:foobar\".',\n      );\n      expect(container.innerHTML).toEqual(\n        '<a href=\"javascript:foobar\">test</a>',\n      );\n    });\n\n    it('Should allow patching link to null', function () {\n      const consoleSpy = spyOn(console, 'error');\n\n      render(<a href=\"javascript:foobar\">test</a>, container);\n\n      expect(consoleSpy).toHaveBeenCalledTimes(1);\n\n      render(<a>test</a>, container);\n\n      expect(consoleSpy).toHaveBeenCalledTimes(1);\n\n      expect(container.innerHTML).toEqual('<a>test</a>');\n    });\n\n    it('Should not log warning when rendering regular link', function () {\n      const consoleSpy = spyOn(console, 'error');\n\n      render(\n        <a href=\"https://github.com/infernojs/inferno\">test</a>,\n        container,\n      );\n\n      expect(consoleSpy).toHaveBeenCalledTimes(0);\n      expect(container.innerHTML).toEqual(\n        '<a href=\"https://github.com/infernojs/inferno\">test</a>',\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/linkEvent.spec.tsx",
    "content": "import { Component, type InfernoNode, linkEvent, render } from 'inferno';\n\ndescribe('linkEvent', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('linkEvent on a button (onClick)', () => {\n    let test;\n\n    function handleOnClick(props): void {\n      test = props.test;\n    }\n\n    function FunctionalComponent(props): InfernoNode {\n      return <button onClick={linkEvent(props, handleOnClick)} />;\n    }\n\n    interface StatefulComponentProps {\n      test?: string;\n    }\n\n    class StatefulComponent extends Component<StatefulComponentProps> {\n      public render(): InfernoNode {\n        return <button onClick={linkEvent(this.props, handleOnClick)} />;\n      }\n    }\n\n    it('should work correctly for functional components', () => {\n      render(<FunctionalComponent test=\"123\" />, container);\n      container.querySelector('button').click();\n      expect(test).toBe('123');\n    });\n\n    it('should work correctly for stateful components', () => {\n      render(<StatefulComponent test=\"456\" />, container);\n      container.querySelector('button').click();\n      expect(test).toBe('456');\n    });\n\n    it('Should not fail when given event is invalid', () => {\n      // @ts-expect-error it should not be possible to assign null event\n      render(<div onClick={linkEvent({ number: 1 }, null)} />, container);\n      container.firstChild.click();\n      // @ts-expect-error it should not be possible to assign undefined event\n      render(<div onClick={linkEvent({ number: 1 }, undefined)} />, container);\n      container.firstChild.click();\n      // @ts-expect-error it should not be possible to assign false event\n      render(<div onClick={linkEvent({ number: 1 }, false)} />, container);\n      container.firstChild.click();\n      // @ts-expect-error it should not be possible to assign true event\n      render(<div onClick={linkEvent({ number: 1 }, true)} />, container);\n      container.firstChild.click();\n      // @ts-expect-error it should not be possible to assign empty obj event\n      render(<div onClick={linkEvent({ number: 1 }, {})} />, container);\n      container.firstChild.click();\n    });\n  });\n\n  describe('linkEvent on a button (onclick) - no delegation', () => {\n    let test;\n\n    function handleOnClick(props): void {\n      test = props.test;\n    }\n\n    function FunctionalComponent(props): InfernoNode {\n      return <button onclick={linkEvent(props, handleOnClick)} />;\n    }\n\n    class StatefulComponent extends Component {\n      public render(): InfernoNode {\n        return <button onclick={linkEvent(this.props, handleOnClick)} />;\n      }\n    }\n\n    it('should work correctly for functional components', () => {\n      render(<FunctionalComponent test=\"123\" />, container);\n      container.querySelector('button').click();\n      expect(test).toBe('123');\n    });\n\n    it('should work correctly for stateful components', () => {\n      render(<StatefulComponent test=\"456\" />, container);\n      container.querySelector('button').click();\n      expect(test).toBe('456');\n    });\n  });\n\n  describe('linkEvent on a input (onInput)', () => {\n    let test;\n    let event;\n\n    function simulateInput(elm) {\n      if (typeof Event !== 'undefined') {\n        const newEvent = document.createEvent('Event');\n        newEvent.initEvent('input', true, true);\n\n        elm.dispatchEvent(newEvent);\n      } else {\n        elm.oninput({\n          target: elm,\n        });\n      }\n    }\n\n    function handleOnInput(props, e) {\n      test = props.test;\n      event = e;\n    }\n\n    function FunctionalComponent(props) {\n      return (\n        <input type=\"text\" onInput={linkEvent(props, handleOnInput)} value=\"\" />\n      );\n    }\n\n    interface StatelessComponentProps {\n      test?: string;\n    }\n\n    class StatefulComponent extends Component<StatelessComponentProps> {\n      public render() {\n        return (\n          <input\n            type=\"text\"\n            onInput={linkEvent(this.props, handleOnInput)}\n            value=\"\"\n          />\n        );\n      }\n    }\n\n    it('should work correctly for functional components', () => {\n      render(<FunctionalComponent test=\"123\" />, container);\n      simulateInput(container.querySelector('input'));\n      expect(test).toBe('123');\n      expect(event.target.nodeName).toBe('INPUT');\n    });\n\n    it('should work correctly for stateful components', () => {\n      render(<StatefulComponent test=\"456\" />, container);\n      simulateInput(container.querySelector('input'));\n      expect(test).toBe('456');\n      expect(event.target.nodeName).toBe('INPUT');\n    });\n  });\n\n  describe('linkEvent on a input (onfocus and onblur) - no delegation', () => {\n    let isFocus;\n    let isBlur;\n\n    function handleOnFocus(id) {\n      isFocus = id;\n    }\n\n    function handleOnBlur(id) {\n      isBlur = id;\n    }\n\n    function FunctionalComponent() {\n      return (\n        <div>\n          <input\n            onFocus={linkEvent('1234', handleOnFocus)}\n            onBlur={linkEvent('4321', handleOnBlur)}\n          />\n        </div>\n      );\n    }\n\n    class StatefulComponent extends Component {\n      public render() {\n        return (\n          <div>\n            <input\n              onFocus={linkEvent('1234', handleOnFocus)}\n              onBlur={linkEvent('4321', handleOnBlur)}\n            />\n          </div>\n        );\n      }\n    }\n\n    function simulateFocus(elm) {\n      if (typeof Event !== 'undefined') {\n        const newEvent = document.createEvent('UIEvent');\n        newEvent.initEvent('focus', true, true);\n\n        elm.dispatchEvent(newEvent);\n      } else {\n        elm.focus();\n      }\n    }\n\n    function simulateBlur(elm) {\n      if (typeof Event !== 'undefined') {\n        const newEvent = document.createEvent('UIEvent');\n        newEvent.initEvent('blur', true, true);\n\n        elm.dispatchEvent(newEvent);\n      } else {\n        elm.blur();\n      }\n    }\n\n    it('should work correctly for functional components', (done) => {\n      render(<FunctionalComponent />, container);\n      const input = container.querySelector('input');\n      simulateFocus(input);\n      setTimeout(() => {\n        simulateBlur(input);\n        setTimeout(() => {\n          expect(isFocus).toBe('1234');\n          expect(isBlur).toBe('4321');\n          done();\n        }, 25);\n      }, 25);\n    });\n\n    it('should work correctly for stateful components', (done) => {\n      render(<StatefulComponent />, container);\n      const input = container.querySelector('input');\n      simulateFocus(input);\n      setTimeout(() => {\n        simulateBlur(input);\n        setTimeout(() => {\n          expect(isFocus).toBe('1234');\n          expect(isBlur).toBe('4321');\n          done();\n        }, 25);\n      }, 25);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/mixedFormElements.spec.tsx",
    "content": "import { render } from 'inferno';\n\ndescribe('HTML Form Elements', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('Textarea - defaultValue', () => {\n    it('Should have value as defaultValue when actual value is null', () => {\n      render(<textarea defaultValue=\"Hey Inferno\" value={null} />, container);\n      expect(container.firstChild.value).toBe('Hey Inferno');\n      expect(container.firstChild.defaultValue).toBe('Hey Inferno');\n    });\n\n    it('Should have value as defaultValue when actual value is undefined', () => {\n      render(<textarea defaultValue=\"Hey Inferno\" />, container);\n      expect(container.firstChild.value).toBe('Hey Inferno');\n      expect(container.firstChild.defaultValue).toBe('Hey Inferno');\n    });\n\n    it('Should not use defaultValue when actual value is empty string', () => {\n      render(<textarea defaultValue=\"Hey Inferno\" value=\"\" />, container);\n      expect(container.firstChild.value).toBe('');\n      expect(container.firstChild.defaultValue).toBe('');\n    });\n\n    it('Should not use defaultValue when actual value is number', () => {\n      render(<textarea defaultValue=\"Hey Inferno\" value={1} />, container);\n      expect(container.firstChild.value).toBe('1');\n      expect(container.firstChild.defaultValue).toBe('1'); // As Per React, its 1 and not Hey Inferno\n    });\n\n    it('Should not use defaultValue when actual value is object', () => {\n      render(\n        // @ts-expect-error\n        <textarea defaultValue=\"Hey Inferno\" value={{ a: 1 }} />,\n        container,\n      );\n      expect(container.firstChild.value).toBe('[object Object]');\n      expect(container.firstChild.defaultValue).toBe('[object Object]');\n    });\n\n    it('Should have false as string when given as defaultValue', () => {\n      // @ts-expect-error\n      render(<textarea defaultValue={false} />, container);\n      expect(container.firstChild.value).toBe('false');\n      expect(container.firstChild.defaultValue).toBe('false');\n    });\n  });\n\n  describe('Input - defaultValue', () => {\n    it('Should have value as defaultValue when actual value is null', () => {\n      render(<input defaultValue=\"Hey Inferno\" value={null} />, container);\n\n      expect(container.firstChild.value).toBe('Hey Inferno');\n      expect(container.firstChild.defaultValue).toBe('Hey Inferno');\n    });\n\n    it('Should have value as defaultValue when actual value is undefined', () => {\n      render(<input defaultValue=\"Hey Inferno\" />, container);\n\n      expect(container.firstChild.value).toBe('Hey Inferno');\n      expect(container.firstChild.defaultValue).toBe('Hey Inferno');\n    });\n\n    it('Should not use defaultValue when actual value is empty string', () => {\n      render(<input defaultValue=\"Hey Inferno\" value=\"\" />, container);\n      expect(container.firstChild.value).toBe('');\n    });\n\n    it('Should not use defaultValue when actual value is number', () => {\n      render(<input defaultValue=\"Hey Inferno\" value={1} />, container);\n      expect(container.firstChild.value).toBe('1');\n      expect(container.firstChild.defaultValue).toBe('1');\n    });\n\n    it('Should not use defaultValue when actual value is object', () => {\n      // @ts-expect-error\n      render(<input defaultValue=\"Hey Inferno\" value={{ a: 1 }} />, container);\n      expect(container.firstChild.value).toBe('[object Object]');\n      expect(container.firstChild.defaultValue).toBe('[object Object]');\n    });\n\n    it('Should be possible to create input with type color', () => {\n      render(<input type=\"color\" />, container);\n      expect(container.firstChild.getAttribute('type')).toBe('color');\n    });\n\n    it('Should be possible to create input with type range', () => {\n      function change() {}\n\n      render(\n        <input min={0} max={255} value={75} onChange={change} type=\"range\" />,\n        container,\n      );\n      expect(container.firstChild.getAttribute('type')).toBe('range');\n      expect(container.firstChild.value).toBe('75');\n\n      render(\n        <input min={0} max={255} value={11} onChange={change} type=\"range\" />,\n        container,\n      );\n\n      const event = document.createEvent('Event');\n      event.initEvent('input', true, true);\n\n      container.firstChild.dispatchEvent(event);\n\n      expect(container.firstChild.getAttribute('type')).toBe('range');\n      expect(container.firstChild.value).toBe('11');\n    });\n  });\n\n  describe('After external change', () => {\n    it('Should update input check property', () => {\n      render(<input type=\"checkbox\" checked={true} />, container);\n      expect(container.innerHTML).toBe('<input type=\"checkbox\">');\n      expect(container.firstChild.checked).toBe(true);\n\n      //\n      // Exernal change verification\n      //\n\n      const input = container.querySelector('input');\n      input.checked = false;\n      expect(container.innerHTML).toBe('<input type=\"checkbox\">');\n      expect(container.firstChild.checked).toBe(false);\n\n      //\n      // New Render\n      //\n\n      render(<input type=\"checkbox\" checked={true} />, container);\n      expect(container.innerHTML).toBe('<input type=\"checkbox\">');\n      expect(container.firstChild.checked).toBe(true);\n    });\n\n    it('Should update textarea value', () => {\n      render(<textarea value=\"Hey People\" />, container);\n      expect(container.firstChild.value).toBe('Hey People');\n      expect(container.firstChild.defaultValue).toBe('Hey People');\n\n      //\n      // Exernal change verification\n      //\n\n      const input = container.querySelector('textarea');\n      input.value = 'Inferno is cool';\n      expect(container.innerHTML).toBe(input.outerHTML);\n      expect(container.firstChild.value).toBe('Inferno is cool');\n\n      //\n      // New Render\n      //\n\n      render(<textarea value=\"Hey People\" />, container);\n      expect(container.firstChild.value).toBe('Hey People');\n      expect(container.firstChild.defaultValue).toBe('Hey People');\n\n      //\n      // New Render, new value\n      //\n\n      render(<textarea value=\"Hey People again\" />, container);\n      expect(container.firstChild.value).toBe('Hey People again');\n      expect(container.firstChild.defaultValue).toBe('Hey People again');\n    });\n\n    it('Should update text input value', () => {\n      render(<input type=\"text\" value=\"Hey People\" />, container);\n      expect(container.firstChild.value).toBe('Hey People');\n\n      //\n      // Exernal change verification\n      //\n\n      const input = container.querySelector('input');\n      input.value = 'Inferno is cool';\n      expect(container.firstChild.value).toBe('Inferno is cool');\n\n      //\n      // New Render\n      //\n\n      render(<input type=\"text\" value=\"Hey People\" />, container);\n      expect(container.firstChild.value).toBe('Hey People');\n\n      //\n      // New Render, new value\n      //\n\n      render(<input type=\"text\" value=\"Hey People again\" />, container);\n      expect(container.firstChild.value).toBe('Hey People again');\n    });\n\n    it('Should update radio button', () => {\n      render(\n        <div>\n          <input type=\"radio\" name=\"gender\" value=\"male\" checked /> Male\n          <input type=\"radio\" name=\"gender\" value=\"female\" /> Female\n          <input type=\"radio\" name=\"gender\" value=\"other\" /> Other\n        </div>,\n        container,\n      );\n\n      expect(container.firstChild.firstChild.value).toBe('male');\n      expect(container.firstChild.firstChild.checked).toBe(true);\n\n      //\n      // Exernal change verification\n      //\n\n      const radiobutton = container.querySelector('input');\n      radiobutton.checked = false;\n      expect(container.firstChild.firstChild.checked).toBe(false);\n\n      //\n      // New Render\n      //\n\n      render(\n        <div>\n          <input type=\"radio\" name=\"gender\" value=\"male\" checked /> Male\n          <input type=\"radio\" name=\"gender\" value=\"female\" /> Female\n          <input type=\"radio\" name=\"gender\" value=\"other\" /> Other\n        </div>,\n        container,\n      );\n\n      expect(container.firstChild.firstChild.value).toBe('male');\n      expect(container.firstChild.firstChild.checked).toBe(true);\n\n      //\n      // New Render, new value\n      //\n\n      render(\n        <div>\n          <input type=\"radio\" name=\"gender\" value=\"male\" /> Male\n          <input type=\"radio\" name=\"gender\" checked value=\"female\" /> Female\n          <input type=\"radio\" name=\"gender\" value=\"other\" /> Other\n        </div>,\n        container,\n      );\n\n      expect(container.firstChild.firstChild.value).toBe('male');\n      expect(container.firstChild.firstChild.checked).toBe(false);\n      expect(container.firstChild.children[1].value).toBe('female');\n      expect(container.firstChild.children[1].checked).toBe(true);\n    });\n\n    it('Should not trigger onClick twice when using synthetic onClick on radio', () => {\n      const spy1 = jasmine.createSpy('spy');\n      const spy2 = jasmine.createSpy('spy');\n      const spy3 = jasmine.createSpy('spy');\n\n      render(\n        <div>\n          <input onClick={spy1} type=\"radio\" name=\"gender\" value=\"male\" />\n          <input onClick={spy2} type=\"radio\" name=\"gender\" value=\"female\" />\n          <input\n            onClick={spy3}\n            type=\"radio\"\n            id=\"test\"\n            name=\"gender\"\n            value=\"other\"\n          />\n        </div>,\n        container,\n      );\n\n      //\n      // Exernal change verification\n      //\n\n      let radiobutton = container.querySelector('#test');\n      radiobutton.click();\n      expect(radiobutton.checked).toBe(true);\n\n      expect(spy1.calls.count()).toBe(0);\n      expect(spy2.calls.count()).toBe(0);\n      expect(spy3.calls.count()).toBe(1);\n\n      //\n      // New Render\n      //\n\n      render(\n        <div>\n          <input onClick={spy1} type=\"radio\" name=\"gender\" value=\"male\" />\n          <input onClick={spy2} type=\"radio\" name=\"gender\" value=\"female\" />\n          <input onClick={spy3} type=\"radio\" name=\"gender\" value=\"other\" />\n        </div>,\n        container,\n      );\n\n      expect(spy1.calls.count()).toBe(0);\n      expect(spy2.calls.count()).toBe(0);\n      expect(spy3.calls.count()).toBe(1);\n\n      //\n      // New Render, new value\n      //\n\n      render(\n        <div>\n          <input onClick={spy1} type=\"radio\" name=\"gender\" value=\"male\" />\n          <input onClick={spy2} type=\"radio\" name=\"gender\" value=\"female\" />\n          <input onClick={spy3} type=\"radio\" name=\"gender\" value=\"other\" />\n        </div>,\n        container,\n      );\n\n      expect(spy1.calls.count()).toBe(0);\n      expect(spy2.calls.count()).toBe(0);\n      expect(spy3.calls.count()).toBe(1);\n\n      render(\n        <div>\n          <input\n            onClick={spy1}\n            type=\"radio\"\n            id=\"test\"\n            name=\"gender\"\n            value=\"male\"\n          />\n          <input onClick={spy2} type=\"radio\" name=\"gender\" value=\"female\" />\n          <input onClick={spy3} type=\"radio\" name=\"gender\" value=\"other\" />\n        </div>,\n        container,\n      );\n\n      expect(spy1.calls.count()).toBe(0);\n      expect(spy2.calls.count()).toBe(0);\n      expect(spy3.calls.count()).toBe(1);\n\n      radiobutton = container.querySelector('#test');\n\n      radiobutton.click();\n\n      expect(spy1.calls.count()).toBe(1);\n      expect(spy2.calls.count()).toBe(0);\n      expect(spy3.calls.count()).toBe(1);\n\n      render(\n        <div>\n          <input\n            onClick={spy1}\n            type=\"radio\"\n            id=\"test\"\n            name=\"gender\"\n            checked={true}\n            value=\"male\"\n          />\n          <input\n            onClick={spy2}\n            type=\"radio\"\n            name=\"gender\"\n            checked={false}\n            value=\"female\"\n          />\n          <input\n            onClick={spy3}\n            type=\"radio\"\n            name=\"gender\"\n            checked={false}\n            value=\"other\"\n          />\n        </div>,\n        container,\n      );\n\n      const node = container.firstChild;\n\n      expect(node.childNodes[0].checked).toBe(true);\n      expect(node.childNodes[1].checked).toBe(false);\n      expect(node.childNodes[2].checked).toBe(false);\n    });\n\n    it('Should change others radio inputs should have single one checked', () => {\n      render(\n        <div>\n          <input type=\"radio\" name=\"gender\" value=\"male\" checked={false} />\n          <input type=\"radio\" name=\"gender\" value=\"female\" checked={true} />\n          <input\n            type=\"radio\"\n            id=\"test\"\n            name=\"gender\"\n            value=\"other\"\n            checked={false}\n          />\n        </div>,\n        container,\n      );\n\n      let node = container.firstChild;\n\n      expect(node.childNodes[0].checked).toBe(false);\n      expect(node.childNodes[1].checked).toBe(true);\n      expect(node.childNodes[2].checked).toBe(false);\n\n      render(\n        <div>\n          <input type=\"radio\" name=\"gender\" value=\"male\" checked={true} />\n          <input type=\"radio\" name=\"gender\" value=\"female\" checked={false} />\n          <input\n            type=\"radio\"\n            id=\"test\"\n            name=\"gender\"\n            value=\"other\"\n            checked={false}\n          />\n        </div>,\n        container,\n      );\n\n      node = container.firstChild;\n\n      expect(node.childNodes[0].checked).toBe(true);\n      expect(node.childNodes[1].checked).toBe(false);\n      expect(node.childNodes[2].checked).toBe(false);\n\n      render(\n        <div>\n          <input type=\"radio\" name=\"gender\" value=\"female\" checked={false} />\n          <input\n            type=\"radio\"\n            id=\"test\"\n            name=\"gender\"\n            value=\"other\"\n            checked={false}\n          />\n        </div>,\n        container,\n      );\n\n      node = container.firstChild;\n\n      expect(node.childNodes[0].checked).toBe(false);\n      expect(node.childNodes[1].checked).toBe(false);\n\n      render(\n        <div>\n          <input type=\"radio\" name=\"gender\" value=\"female\" checked={false} />\n          <input\n            type=\"radio\"\n            id=\"test\"\n            name=\"gender\"\n            value=\"other\"\n            checked={true}\n          />\n        </div>,\n        container,\n      );\n\n      node = container.firstChild;\n\n      expect(node.childNodes[0].checked).toBe(false);\n      expect(node.childNodes[1].checked).toBe(true);\n\n      render(\n        <div>\n          <input type=\"radio\" name=\"gender\" value=\"female\" checked={false} />\n          <input\n            type=\"radio\"\n            id=\"test\"\n            name=\"gender\"\n            value=\"other\"\n            checked={true}\n          />\n          <input type=\"radio\" name=\"gender\" value=\"female\" checked={false} />\n          <input type=\"radio\" name=\"gender\" value=\"dqw\" checked={false} />\n        </div>,\n        container,\n      );\n\n      node = container.firstChild;\n\n      expect(node.childNodes[0].checked).toBe(false);\n      expect(node.childNodes[1].checked).toBe(true);\n      expect(node.childNodes[2].checked).toBe(false);\n      expect(node.childNodes[3].checked).toBe(false);\n\n      render(\n        <div>\n          <input type=\"radio\" name=\"gender\" value=\"female\" checked={false} />\n        </div>,\n        container,\n      );\n\n      node = container.firstChild;\n\n      expect(node.childNodes[0].checked).toBe(false);\n\n      render(\n        <div>\n          <input type=\"radio\" name=\"gender\" value=\"female\" checked={true} />\n        </div>,\n        container,\n      );\n\n      node = container.firstChild;\n\n      expect(node.childNodes[0].checked).toBe(true);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/newlifecycle.spec.tsx",
    "content": "import { Component, render, rerender } from 'inferno';\n\ndescribe('Lifecycle methods', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should call nested new lifecycle methods in the right order', () => {\n    let updateOuterState;\n    let updateInnerState;\n    let forceUpdateOuter;\n    let forceUpdateInner;\n\n    let log: string[];\n    const logger = function (msg) {\n      return function () {\n        // return true for shouldComponentUpdate\n        log.push(msg);\n        return true;\n      };\n    };\n\n    interface OuterState {\n      value: number;\n    }\n\n    interface OuterProps {\n      value?: number;\n      x: number;\n    }\n\n    class Outer extends Component<OuterProps, OuterState> {\n      public state: OuterState;\n\n      public static getDerivedStateFromProps() {\n        log.push('outer getDerivedStateFromProps');\n        return null;\n      }\n\n      constructor() {\n        super();\n        log.push('outer constructor');\n\n        this.state = { value: 0 };\n        forceUpdateOuter = () => {\n          this.forceUpdate();\n        };\n        updateOuterState = () => {\n          this.setState({\n            value: (this.state.value + 1) % 2,\n          });\n        };\n      }\n\n      public render() {\n        log.push('outer render');\n        return (\n          <div>\n            <Inner x={this.props.x} outerValue={this.state.value} />\n          </div>\n        );\n      }\n    }\n\n    Outer.prototype.componentDidMount = logger('outer componentDidMount');\n    Outer.prototype.shouldComponentUpdate = logger(\n      'outer shouldComponentUpdate',\n    );\n    Outer.prototype.getSnapshotBeforeUpdate = logger(\n      'outer getSnapshotBeforeUpdate',\n    );\n    Outer.prototype.componentDidUpdate = logger('outer componentDidUpdate');\n    Outer.prototype.componentWillUnmount = logger('outer componentWillUnmount');\n\n    interface InnerProps {\n      x: number;\n      outerValue: number;\n    }\n\n    interface InnerState {\n      value: number;\n    }\n\n    class Inner extends Component<InnerProps, InnerState> {\n      public state: InnerState;\n\n      public static getDerivedStateFromProps() {\n        log.push('inner getDerivedStateFromProps');\n        return null;\n      }\n\n      constructor() {\n        super();\n        log.push('inner constructor');\n\n        this.state = { value: 0 };\n        forceUpdateInner = () => {\n          this.forceUpdate();\n        };\n        updateInnerState = () => {\n          this.setState({\n            value: (this.state.value + 1) % 2,\n          });\n        };\n      }\n\n      public render() {\n        log.push('inner render');\n        return (\n          <span>\n            {this.props.x} {this.props.outerValue} {this.state.value}\n          </span>\n        );\n      }\n    }\n\n    Inner.prototype.componentDidMount = logger('inner componentDidMount');\n    Inner.prototype.shouldComponentUpdate = logger(\n      'inner shouldComponentUpdate',\n    );\n    Inner.prototype.getSnapshotBeforeUpdate = logger(\n      'inner getSnapshotBeforeUpdate',\n    );\n    Inner.prototype.componentDidUpdate = logger('inner componentDidUpdate');\n    Inner.prototype.componentWillUnmount = logger('inner componentWillUnmount');\n\n    // Constructor & mounting\n    log = [];\n    render(<Outer x={1} />, container);\n    expect(log).toEqual([\n      'outer constructor',\n      'outer getDerivedStateFromProps',\n      'outer render',\n      'inner constructor',\n      'inner getDerivedStateFromProps',\n      'inner render',\n      'inner componentDidMount',\n      'outer componentDidMount',\n    ]);\n\n    // Outer & Inner props update\n    log = [];\n    render(<Outer x={2} />, container);\n    // Note: we differ from React here in that we apply changes to the dom\n    // as we find them while diffing. React on the other hand separates this\n    // into specific phases, meaning changes to the dom are only flushed\n    // once the whole diff-phase is complete. This is why\n    // \"outer getSnapshotBeforeUpdate\" is called just before the \"inner\" hooks.\n    // For react this call would be right before \"outer componentDidUpdate\"\n    expect(log).toEqual([\n      'outer getDerivedStateFromProps',\n      'outer shouldComponentUpdate',\n      'outer render',\n      'outer getSnapshotBeforeUpdate',\n      'inner getDerivedStateFromProps',\n      'inner shouldComponentUpdate',\n      'inner render',\n      'inner getSnapshotBeforeUpdate',\n      'inner componentDidUpdate',\n      'outer componentDidUpdate',\n    ]);\n\n    // Outer state update & Inner props update\n    log = [];\n    updateOuterState();\n    rerender();\n    expect(log).toEqual([\n      'outer getDerivedStateFromProps',\n      'outer shouldComponentUpdate',\n      'outer render',\n      'outer getSnapshotBeforeUpdate',\n      'inner getDerivedStateFromProps',\n      'inner shouldComponentUpdate',\n      'inner render',\n      'inner getSnapshotBeforeUpdate',\n      'inner componentDidUpdate',\n      'outer componentDidUpdate',\n    ]);\n\n    // Inner state update\n    log = [];\n    updateInnerState();\n    rerender();\n    expect(log).toEqual([\n      'inner getDerivedStateFromProps',\n      'inner shouldComponentUpdate',\n      'inner render',\n      'inner getSnapshotBeforeUpdate',\n      'inner componentDidUpdate',\n    ]);\n\n    // Force update Outer\n    log = [];\n    forceUpdateOuter();\n    rerender();\n    expect(log).toEqual([\n      'outer getDerivedStateFromProps',\n      'outer render',\n      'outer getSnapshotBeforeUpdate',\n      'inner getDerivedStateFromProps',\n      'inner shouldComponentUpdate',\n      'inner render',\n      'inner getSnapshotBeforeUpdate',\n      'inner componentDidUpdate',\n      'outer componentDidUpdate',\n    ]);\n\n    // Force update Inner\n    log = [];\n    forceUpdateInner();\n    rerender();\n    expect(log).toEqual([\n      'inner getDerivedStateFromProps',\n      'inner render',\n      'inner getSnapshotBeforeUpdate',\n      'inner componentDidUpdate',\n    ]);\n\n    // Unmounting Outer & Inner\n    log = [];\n    render(<table />, container);\n    expect(log).toEqual([\n      'outer componentWillUnmount',\n      'inner componentWillUnmount',\n    ]);\n  });\n\n  describe('static getDerivedStateFromProps', () => {\n    it('should set initial state with value returned from getDerivedStateFromProps', () => {\n      interface FooState {\n        bar: string;\n        foo: string;\n      }\n\n      class Foo extends Component<{ foo: string }, FooState> {\n        public state: FooState;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            bar: '',\n            foo: '',\n          };\n        }\n\n        public static getDerivedStateFromProps(nextProps) {\n          return {\n            bar: 'bar',\n            foo: nextProps.foo,\n          };\n        }\n\n        public render() {\n          return <div className={`${this.state.foo} ${this.state.bar}`} />;\n        }\n      }\n\n      render(<Foo foo=\"foo\" />, container);\n      expect(container.firstChild.className).toEqual('foo bar');\n    });\n\n    it('should update initial state with value returned from getDerivedStateFromProps', () => {\n      interface FooState {\n        bar: string;\n        foo: string;\n      }\n      class Foo extends Component<unknown, FooState> {\n        public state: FooState;\n\n        constructor(props, context) {\n          super(props, context);\n          this.state = {\n            bar: 'bar',\n            foo: 'foo',\n          };\n        }\n\n        public static getDerivedStateFromProps(_nextProps, prevState) {\n          return {\n            foo: `not-${prevState.foo}`,\n          };\n        }\n\n        public render() {\n          return <div className={`${this.state.foo} ${this.state.bar}`} />;\n        }\n      }\n\n      render(<Foo />, container);\n      expect(container.firstChild.className).toEqual('not-foo bar');\n    });\n\n    it(\"should update the instance's state with the value returned from getDerivedStateFromProps when props change\", () => {\n      interface FooState {\n        value: string;\n      }\n\n      interface FooProps {\n        update: boolean;\n      }\n\n      class Foo extends Component<FooProps, FooState> {\n        public state: FooState;\n        constructor(props, context) {\n          super(props, context);\n          this.state = {\n            value: 'initial',\n          };\n        }\n\n        public static getDerivedStateFromProps(nextProps) {\n          if (nextProps.update) {\n            return {\n              value: 'updated',\n            };\n          }\n\n          return null;\n        }\n\n        public componentDidMount() {}\n\n        public componentDidUpdate() {}\n\n        public render() {\n          return <div className={this.state.value} />;\n        }\n      }\n\n      const derivedSpy = spyOn(\n        Foo,\n        'getDerivedStateFromProps',\n      ).and.callThrough();\n      const didMountSpy = spyOn(Foo.prototype, 'componentDidMount');\n      const didUpdateSpy = spyOn(Foo.prototype, 'componentDidUpdate');\n\n      render(<Foo update={false} />, container);\n      expect(container.firstChild.className).toEqual('initial');\n      expect(derivedSpy.calls.count()).toBe(1);\n      expect(didMountSpy.calls.count()).toBe(1); // verify mount occurred\n      expect(didUpdateSpy.calls.count()).toBe(0);\n\n      render(<Foo update={true} />, container);\n      expect(container.firstChild.className).toEqual('updated');\n      expect(derivedSpy.calls.count()).toBe(2);\n      expect(didMountSpy.calls.count()).toBe(1);\n      expect(didUpdateSpy.calls.count()).toBe(1); // verify update occurred\n    });\n\n    it(\"should update the instance's state with the value returned from getDerivedStateFromProps when state changes\", () => {\n      interface FooState {\n        value: string;\n      }\n\n      class Foo extends Component<unknown, FooState> {\n        public state: FooState;\n\n        constructor(props, context) {\n          super(props, context);\n          this.state = {\n            value: 'initial',\n          };\n        }\n\n        public static getDerivedStateFromProps(_nextProps, prevState) {\n          // Don't change state for call that happens after the constructor\n          if (prevState.value === 'initial') {\n            return null;\n          }\n\n          return {\n            value: prevState.value + ' derived',\n          };\n        }\n\n        public componentDidMount() {\n          this.setState({ value: 'updated' });\n        }\n\n        public render() {\n          return <div className={this.state.value} />;\n        }\n      }\n\n      const derivedSpy = spyOn(\n        Foo,\n        'getDerivedStateFromProps',\n      ).and.callThrough();\n\n      render(<Foo />, container);\n      expect(container.firstChild.className).toEqual('initial');\n      expect(derivedSpy.calls.count()).toBe(1);\n\n      rerender(); // call rerender to handle cDM setState call\n      expect(container.firstChild.className).toEqual('updated derived');\n      expect(derivedSpy.calls.count()).toBe(2);\n    });\n\n    it('should NOT modify state if null is returned', () => {\n      interface FooState {\n        bar: string;\n        foo: string;\n      }\n\n      class Foo extends Component<unknown, FooState> {\n        public state: FooState;\n        constructor(props, context) {\n          super(props, context);\n          this.state = {\n            bar: 'bar',\n            foo: 'foo',\n          };\n        }\n\n        public static getDerivedStateFromProps() {\n          return null;\n        }\n\n        public render() {\n          return <div className={`${this.state.foo} ${this.state.bar}`} />;\n        }\n      }\n\n      const derivedSpy = spyOn(Foo, 'getDerivedStateFromProps');\n\n      render(<Foo />, container);\n      expect(container.firstChild.className).toEqual('foo bar');\n      expect(derivedSpy.calls.count()).toBe(1);\n    });\n\n    // NOTE: Difference from React\n    // React v16.3.2 warns if undefined if returned from getDerivedStateFromProps\n    it('should NOT modify state if undefined is returned', () => {\n      interface FooState {\n        bar: string;\n        foo: string;\n      }\n\n      class Foo extends Component<unknown, FooState> {\n        public state: FooState;\n        constructor(props, context) {\n          super(props, context);\n          this.state = {\n            bar: 'bar',\n            foo: 'foo',\n          };\n        }\n\n        public static getDerivedStateFromProps() {}\n\n        public render() {\n          return <div className={`${this.state.foo} ${this.state.bar}`} />;\n        }\n      }\n\n      const derivedSpy = spyOn(Foo, 'getDerivedStateFromProps');\n\n      render(<Foo />, container);\n      expect(container.firstChild.className).toEqual('foo bar');\n      expect(derivedSpy.calls.count()).toBe(1);\n    });\n\n    it('should NOT invoke deprecated lifecycles (cWM/cWRP) if new static gDSFP is present', () => {\n      class Foo extends Component {\n        public static getDerivedStateFromProps() {}\n\n        public componentWillMount() {}\n\n        public componentWillReceiveProps() {}\n\n        public render() {\n          return <div />;\n        }\n      }\n\n      const derivedSpy = spyOn(Foo, 'getDerivedStateFromProps');\n      const willMountSpy = spyOn(Foo.prototype, 'componentWillMount');\n      const propsSpy = spyOn(Foo.prototype, 'componentWillReceiveProps');\n\n      render(<Foo />, container);\n      expect(derivedSpy.calls.count()).toBe(1);\n      expect(willMountSpy.calls.count()).toBe(0);\n      expect(propsSpy.calls.count()).toBe(0);\n    });\n\n    it('is not called if neither state nor props have changed', () => {\n      let logs: string[] = [];\n      let childRef;\n\n      interface ParentState {\n        parentRenders: number;\n      }\n\n      class Parent extends Component<unknown, ParentState> {\n        public state: ParentState;\n        constructor(props) {\n          super(props);\n          this.state = { parentRenders: 0 };\n        }\n\n        public static getDerivedStateFromProps(_props, prevState) {\n          logs.push('parent getDerivedStateFromProps');\n          return prevState.parentRenders + 1;\n        }\n\n        public render() {\n          logs.push('parent render');\n          return (\n            <Child\n              parentRenders={this.state.parentRenders}\n              ref={(child) => (childRef = child)}\n            />\n          );\n        }\n      }\n\n      interface ChildProps {\n        parentRenders: number;\n      }\n\n      class Child extends Component<ChildProps> {\n        public render() {\n          logs.push('child render');\n          return this.props.parentRenders;\n        }\n      }\n\n      render(<Parent />, container);\n      expect(logs).toEqual([\n        'parent getDerivedStateFromProps',\n        'parent render',\n        'child render',\n      ]);\n\n      logs = [];\n      childRef.setState({});\n      rerender();\n      expect(logs).toEqual(['child render']);\n    });\n\n    it('should be passed next props and state', () => {\n      let updateState;\n\n      let propsArg;\n      let stateArg;\n\n      interface FooState {\n        value: number;\n      }\n\n      class Foo extends Component<{ foo: string }, FooState> {\n        public state: FooState;\n        constructor(props) {\n          super(props);\n          this.state = {\n            value: 0,\n          };\n          updateState = () => {\n            this.setState({\n              value: this.state.value + 1,\n            });\n          };\n        }\n\n        public static getDerivedStateFromProps(props, state) {\n          // These object references might be updated later so copy\n          // object so we can assert their values at this snapshot in time\n          propsArg = { ...props };\n          stateArg = { ...state };\n\n          // NOTE: Don't do this in real production code!\n          // https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html\n          return {\n            value: state.value + 1,\n          };\n        }\n\n        public render() {\n          return <div>{this.state.value}</div>;\n        }\n      }\n\n      // Initial render\n      // state.value: initialized to 0 in constructor, 0 -> 1 in gDSFP\n\n      render(<Foo foo=\"foo\" />, container);\n      expect(container.firstChild.textContent).toEqual('1');\n      expect(propsArg).toEqual({\n        foo: 'foo',\n      });\n      expect(stateArg).toEqual({\n        value: 0,\n      });\n\n      // New Props\n      // state.value: 1 -> 2 in gDSFP\n      render(<Foo foo=\"bar\" />, container);\n      expect(container.firstChild.textContent).toEqual('2');\n      expect(propsArg).toEqual({\n        foo: 'bar',\n      });\n      expect(stateArg).toEqual({\n        value: 1,\n      });\n\n      // New state\n      // state.value: 2 -> 3 in updateState, 3\n      updateState();\n      rerender();\n      expect(container.firstChild.textContent).toEqual('4');\n      expect(propsArg).toEqual({\n        foo: 'bar',\n      });\n      expect(stateArg).toEqual({\n        value: 3,\n      });\n    });\n\n    it('should NOT mutate state, only create new versions', () => {\n      const stateConstant = {};\n      let componentState;\n\n      class Stateful extends Component {\n        public static getDerivedStateFromProps() {\n          return { key: 'value' };\n        }\n\n        constructor() {\n          super(...arguments);\n          this.state = stateConstant;\n        }\n\n        public componentDidMount() {\n          componentState = this.state;\n        }\n      }\n\n      render(<Stateful />, container);\n\n      expect(componentState).toEqual({ key: 'value' });\n      expect(stateConstant).toEqual({});\n    });\n  });\n\n  describe('#getSnapshotBeforeUpdate', () => {\n    it('should pass the return value from getSnapshotBeforeUpdate to componentDidUpdate', () => {\n      let log: string[] = [];\n\n      interface MyComponentProps {\n        value: string;\n      }\n      interface MyComponentState {\n        value: number;\n      }\n\n      class MyComponent extends Component<MyComponentProps, MyComponentState> {\n        constructor(props) {\n          super(props);\n          this.state = {\n            value: 0,\n          };\n        }\n\n        public static getDerivedStateFromProps(_nextProps, prevState) {\n          return {\n            value: prevState.value + 1,\n          };\n        }\n\n        public getSnapshotBeforeUpdate(prevProps, prevState) {\n          log.push(\n            `getSnapshotBeforeUpdate() prevProps:${prevProps.value} prevState:${prevState.value}`,\n          );\n          return 'abc';\n        }\n\n        public componentDidUpdate(prevProps, prevState, snapshot) {\n          log.push(\n            `componentDidUpdate() prevProps:${prevProps.value} prevState:${prevState.value} snapshot:${snapshot}`,\n          );\n        }\n\n        public render() {\n          log.push('render');\n          return null;\n        }\n      }\n\n      render(<MyComponent value=\"foo\" />, container);\n      expect(log).toEqual(['render']);\n      log = [];\n\n      render(<MyComponent value=\"bar\" />, container);\n      expect(log).toEqual([\n        'render',\n        'getSnapshotBeforeUpdate() prevProps:foo prevState:1',\n        'componentDidUpdate() prevProps:foo prevState:1 snapshot:abc',\n      ]);\n      log = [];\n\n      render(<MyComponent value=\"baz\" />, container);\n      expect(log).toEqual([\n        'render',\n        'getSnapshotBeforeUpdate() prevProps:bar prevState:2',\n        'componentDidUpdate() prevProps:bar prevState:2 snapshot:abc',\n      ]);\n      log = [];\n\n      render(<div />, container);\n      expect(log).toEqual([]);\n    });\n\n    it('should call getSnapshotBeforeUpdate before mutations are committed', () => {\n      let log: string[] = [];\n\n      interface MyComponentProps {\n        value: string;\n      }\n      interface MyComponentState {\n        value: number;\n      }\n\n      class MyComponent extends Component<MyComponentProps, MyComponentState> {\n        protected divRef: HTMLDivElement | null;\n\n        public getSnapshotBeforeUpdate(prevProps) {\n          log.push('getSnapshotBeforeUpdate');\n          expect(this.divRef!.textContent).toEqual(`value:${prevProps.value}`);\n          return 'foobar';\n        }\n\n        public componentDidUpdate(_prevProps, _prevState, snapshot) {\n          log.push('componentDidUpdate');\n          expect(this.divRef!.textContent).toEqual(`value:${this.props.value}`);\n          expect(snapshot).toEqual('foobar');\n        }\n\n        public render() {\n          log.push('render');\n          return (\n            <div\n              ref={(ref) => (this.divRef = ref)}\n            >{`value:${this.props.value}`}</div>\n          );\n        }\n      }\n\n      render(<MyComponent value=\"foo\" />, container);\n      expect(log).toEqual(['render']);\n      log = [];\n\n      render(<MyComponent value=\"bar\" />, container);\n      expect(log).toEqual([\n        'render',\n        'getSnapshotBeforeUpdate',\n        'componentDidUpdate',\n      ]);\n    });\n\n    it('should be passed the previous props and state', () => {\n      let updateState;\n      let prevPropsArg;\n      let prevStateArg;\n      let curProps;\n      let curState;\n\n      interface FooState {\n        value: number;\n      }\n\n      interface FooProps {\n        foo: string;\n      }\n\n      class Foo extends Component<FooProps, FooState> {\n        public state: FooState;\n        constructor(props) {\n          super(props);\n          this.state = {\n            value: 0,\n          };\n          updateState = () => {\n            this.setState({\n              value: this.state.value + 1,\n            });\n          };\n        }\n\n        public static getDerivedStateFromProps(_props, state) {\n          // NOTE: Don't do this in real production code!\n          // https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html\n          return {\n            value: state.value + 1,\n          };\n        }\n\n        public getSnapshotBeforeUpdate(prevProps, prevState) {\n          // These object references might be updated later so copy\n          // object so we can assert their values at this snapshot in time\n          prevPropsArg = { ...prevProps };\n          prevStateArg = { ...prevState };\n\n          curProps = { ...this.props };\n          curState = { ...this.state };\n        }\n\n        public render() {\n          return <div>{this.state.value}</div>;\n        }\n      }\n\n      // Expectation:\n      // `prevState` in getSnapshotBeforeUpdate should be\n      // the state before setState or getDerivedStateFromProps was called.\n      // `this.state` in getSnapshotBeforeUpdate should be\n      // the updated state after getDerivedStateFromProps was called.\n\n      // Initial render\n      // state.value: initialized to 0 in constructor, 0 -> 1 in gDSFP\n      render(<Foo foo=\"foo\" />, container);\n      expect(container.firstChild.textContent).toEqual('1');\n      expect(prevPropsArg).toBeUndefined();\n      expect(prevStateArg).toBeUndefined();\n      expect(curProps).toBeUndefined();\n      expect(curState).toBeUndefined();\n\n      // New props\n      // state.value: 1 -> 2 in gDSFP\n      render(<Foo foo=\"bar\" />, container);\n      expect(container.firstChild.textContent).toEqual('2');\n      expect(prevPropsArg).toEqual({\n        foo: 'foo',\n      });\n      expect(prevStateArg).toEqual({\n        value: 1,\n      });\n      expect(curProps).toEqual({\n        foo: 'bar',\n      });\n      expect(curState).toEqual({\n        value: 2,\n      });\n\n      // New state\n      // state.value: 2 -> 3 in updateState, 3\n      updateState();\n      rerender();\n      expect(container.firstChild.textContent).toEqual('4');\n      expect(prevPropsArg).toEqual({\n        foo: 'bar',\n      });\n      expect(prevStateArg).toEqual({\n        value: 2,\n      });\n      expect(curProps).toEqual({\n        foo: 'bar',\n      });\n      expect(curState).toEqual({\n        value: 4,\n      });\n    });\n  });\n\n  describe('#componentWillUpdate', () => {\n    it('should NOT be called on initial render', () => {\n      class ReceivePropsComponent extends Component {\n        public componentWillUpdate() {}\n\n        public render() {\n          return <div />;\n        }\n      }\n\n      const willUpdateSpy = spyOn(\n        ReceivePropsComponent.prototype,\n        'componentWillUpdate',\n      );\n      render(<ReceivePropsComponent />, container);\n      expect(willUpdateSpy.calls.count()).toBe(0);\n    });\n\n    it('should be called when rerender with new props from parent', () => {\n      let doRender;\n\n      interface OuterState {\n        i: number;\n      }\n\n      class Outer extends Component<unknown, OuterState> {\n        public state: OuterState;\n\n        constructor(p, c) {\n          super(p, c);\n          this.state = { i: 0 };\n        }\n\n        public componentDidMount() {\n          doRender = () => {\n            this.setState({ i: this.state.i + 1 });\n          };\n        }\n\n        public render(props, { i }) {\n          return <Inner i={i} {...props} />;\n        }\n      }\n\n      class Inner extends Component {\n        public componentWillUpdate(nextProps, nextState) {\n          expect(nextProps).toEqual({ i: 1 });\n          expect(nextState).toBe(null);\n        }\n\n        public render() {\n          return <div />;\n        }\n      }\n\n      const willUpdateSpy = spyOn(\n        Inner.prototype,\n        'componentWillUpdate',\n      ).and.callThrough();\n\n      // Initial render\n      render(<Outer />, container);\n      expect(willUpdateSpy.calls.count()).toBe(0);\n\n      // Rerender inner with new props\n      doRender();\n      rerender();\n      expect(willUpdateSpy.calls.count()).toBe(1);\n    });\n\n    it('should be called on new state', () => {\n      let doRender;\n\n      interface ReceivePropsComponentState {\n        i: number;\n      }\n\n      class ReceivePropsComponent extends Component<\n        unknown,\n        ReceivePropsComponentState\n      > {\n        public state: ReceivePropsComponentState;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            i: 0,\n          };\n        }\n\n        public componentWillUpdate() {}\n\n        public componentDidMount() {\n          doRender = () => {\n            this.setState({ i: this.state.i + 1 });\n          };\n        }\n\n        public render() {\n          return <div />;\n        }\n      }\n\n      const willUpdateSpy = spyOn(\n        ReceivePropsComponent.prototype,\n        'componentWillUpdate',\n      );\n      render(<ReceivePropsComponent />, container);\n      expect(willUpdateSpy.calls.count()).toBe(0);\n\n      doRender();\n      rerender();\n      expect(willUpdateSpy.calls.count()).toBe(1);\n    });\n\n    it('should be called after children are mounted', () => {\n      const log: string[] = [];\n\n      class Inner extends Component {\n        public componentDidMount() {\n          log.push('Inner mounted');\n\n          // Verify that the component is actually mounted when this\n          // callback is invoked.\n          expect(container.querySelector('#inner')).toEqual(this.$LI.dom);\n        }\n\n        public render() {\n          return <div id=\"inner\" />;\n        }\n      }\n\n      class Outer extends Component<{ renderInner?: boolean }> {\n        public componentDidUpdate() {\n          log.push('Outer updated');\n        }\n\n        public render(props) {\n          return props.renderInner ? <Inner /> : <div />;\n        }\n      }\n\n      render(<Outer renderInner={false} />, container);\n      render(<Outer renderInner={true} />, container);\n\n      expect(log).toEqual(['Inner mounted', 'Outer updated']);\n    });\n  });\n\n  describe('#componentWillReceiveProps', () => {\n    it('should NOT be called on initial render', () => {\n      class ReceivePropsComponent extends Component {\n        public componentWillReceiveProps() {}\n\n        public render() {\n          return <div />;\n        }\n      }\n\n      const willRecSpy = spyOn(\n        ReceivePropsComponent.prototype,\n        'componentWillReceiveProps',\n      );\n      render(<ReceivePropsComponent />, container);\n      expect(willRecSpy.calls.count()).toBe(0);\n    });\n\n    it('should be called when rerender with new props from parent', () => {\n      let doRender;\n\n      interface OuterState {\n        i: number;\n      }\n\n      class Outer extends Component<unknown, OuterState> {\n        public state: OuterState;\n\n        constructor(p, c) {\n          super(p, c);\n          this.state = { i: 0 };\n        }\n\n        public componentDidMount() {\n          doRender = () => {\n            this.setState({ i: this.state.i + 1 });\n          };\n        }\n\n        public render(props, { i }) {\n          return <Inner i={i} {...props} />;\n        }\n      }\n\n      interface InnerProps {\n        i: number;\n      }\n\n      class Inner extends Component<InnerProps> {\n        public componentWillMount() {\n          expect(this.props.i).toEqual(0);\n        }\n\n        public componentWillReceiveProps(nextProps) {\n          expect(nextProps.i).toEqual(1);\n        }\n\n        public render() {\n          return <div />;\n        }\n      }\n\n      const cwrpSpy = spyOn(\n        Inner.prototype,\n        'componentWillReceiveProps',\n      ).and.callThrough();\n\n      // Initial render\n      render(<Outer />, container);\n      expect(cwrpSpy.calls.count()).toBe(0);\n\n      // Rerender inner with new props\n      doRender();\n      rerender();\n      expect(cwrpSpy.calls.count()).toBe(1);\n    });\n\n    it('should be called in right execution order', () => {\n      let doRender;\n\n      interface OuterState {\n        i: number;\n      }\n\n      class Outer extends Component<unknown, OuterState> {\n        public state: OuterState;\n        constructor(p, c) {\n          super(p, c);\n          this.state = { i: 0 };\n        }\n\n        public componentDidMount() {\n          doRender = () => {\n            this.setState({ i: this.state.i + 1 });\n          };\n        }\n\n        public render(props, { i }) {\n          return <Inner i={i} {...props} />;\n        }\n      }\n\n      class Inner extends Component {\n        public componentDidUpdate() {\n          expect(cwrpSpy.calls.count()).toBe(1);\n          expect(cwuSpy.calls.count()).toBe(1);\n        }\n\n        public componentWillReceiveProps() {\n          expect(cwuSpy.calls.count()).toBe(0);\n          expect(cduSpy.calls.count()).toBe(0);\n        }\n\n        public componentWillUpdate() {\n          expect(cwrpSpy.calls.count()).toBe(1);\n          expect(cduSpy.calls.count()).toBe(0);\n        }\n\n        public render() {\n          return <div />;\n        }\n      }\n\n      const orderOfCalls: string[] = [];\n      const cwrpSpy = spyOn(\n        Inner.prototype,\n        'componentWillReceiveProps',\n      ).and.callFake(function () {\n        orderOfCalls.push('componentWillReceiveProps');\n      });\n      const cduSpy = spyOn(Inner.prototype, 'componentDidUpdate').and.callFake(\n        function () {\n          orderOfCalls.push('componentDidUpdate');\n        },\n      );\n      const cwuSpy = spyOn(Inner.prototype, 'componentWillUpdate').and.callFake(\n        function () {\n          orderOfCalls.push('componentWillUpdate');\n        },\n      );\n      const originalDidMount = Outer.prototype.componentDidMount;\n      const cdmSpy = spyOn(Outer.prototype, 'componentDidMount').and.callFake(\n        function () {\n          orderOfCalls.push('componentDidMount');\n          originalDidMount.call(this);\n        },\n      );\n\n      render(<Outer />, container);\n      doRender();\n      rerender();\n\n      expect(orderOfCalls).toEqual([\n        'componentDidMount',\n        'componentWillReceiveProps',\n        'componentWillUpdate',\n        'componentDidUpdate',\n      ]);\n\n      expect(cdmSpy.calls.count()).toBe(1);\n    });\n  });\n\n  describe('#componentDidUpdate', () => {\n    it('should be passed previous props and state', () => {\n      let updateState;\n\n      let prevPropsArg;\n      let prevStateArg;\n      let curProps;\n      let curState;\n\n      interface FooProps {\n        foo: string;\n      }\n\n      interface FooState {\n        value: number;\n      }\n\n      class Foo extends Component<FooProps, FooState> {\n        public state: FooState;\n        constructor(props) {\n          super(props);\n          this.state = {\n            value: 0,\n          };\n          updateState = () => {\n            this.setState({\n              value: this.state.value + 1,\n            });\n          };\n        }\n\n        public static getDerivedStateFromProps(_props, state) {\n          // NOTE: Don't do this in real production code!\n          // https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html\n          return {\n            value: state.value + 1,\n          };\n        }\n\n        public componentDidUpdate(prevProps, prevState) {\n          // These object references might be updated later so copy\n          // object so we can assert their values at this snapshot in time\n          prevPropsArg = { ...prevProps };\n          prevStateArg = { ...prevState };\n\n          curProps = { ...this.props };\n          curState = { ...this.state };\n        }\n\n        public render() {\n          return <div>{this.state.value}</div>;\n        }\n      }\n\n      // Expectation:\n      // `prevState` in componentDidUpdate should be\n      // the state before setState and getDerivedStateFromProps was called.\n      // `this.state` in componentDidUpdate should be\n      // the updated state after getDerivedStateFromProps was called.\n\n      // Initial render\n      // state.value: initialized to 0 in constructor, 0 -> 1 in gDSFP\n      render(<Foo foo=\"foo\" />, container);\n      expect(container.firstChild.textContent).toEqual('1');\n      expect(prevPropsArg).toBeUndefined();\n      expect(prevStateArg).toBeUndefined();\n      expect(curProps).toBeUndefined();\n      expect(curState).toBeUndefined();\n\n      // New props\n      // state.value: 1 -> 2 in gDSFP\n      render(<Foo foo=\"bar\" />, container);\n      expect(container.firstChild.textContent).toEqual('2');\n      expect(prevPropsArg).toEqual({\n        foo: 'foo',\n      });\n      expect(prevStateArg).toEqual({\n        value: 1,\n      });\n      expect(curProps).toEqual({\n        foo: 'bar',\n      });\n      expect(curState).toEqual({\n        value: 2,\n      });\n\n      // New state\n      // state.value: 2 -> 3 in updateState, 3\n      updateState();\n      rerender();\n      expect(container.firstChild.textContent).toEqual('4');\n      expect(prevPropsArg).toEqual({\n        foo: 'bar',\n      });\n      expect(prevStateArg).toEqual({\n        value: 2,\n      });\n      expect(curProps).toEqual({\n        foo: 'bar',\n      });\n      expect(curState).toEqual({\n        value: 4,\n      });\n    });\n\n    it(\"prevState argument should be the same object if state doesn't change\", () => {\n      let changeProps;\n      let cduPrevState;\n      let cduCurrentState;\n\n      interface PropsProviderState {\n        value: number;\n      }\n\n      class PropsProvider extends Component<unknown, PropsProviderState> {\n        public state: PropsProviderState;\n\n        constructor() {\n          super();\n          this.state = { value: 0 };\n          changeProps = this.changeReceiverProps.bind(this);\n        }\n\n        public changeReceiverProps() {\n          const value = (this.state.value + 1) % 2;\n          this.setState({\n            value,\n          });\n        }\n\n        public render() {\n          return <PropsReceiver value={this.state.value} />;\n        }\n      }\n\n      interface PropsReceiverProps {\n        value: number;\n      }\n\n      class PropsReceiver extends Component<PropsReceiverProps> {\n        public componentDidUpdate(_prevProps, prevState) {\n          cduPrevState = prevState;\n          cduCurrentState = this.state;\n        }\n\n        public render({ value }) {\n          return <div>{value}</div>;\n        }\n      }\n\n      render(<PropsProvider />, container);\n\n      changeProps();\n      rerender();\n\n      expect(cduPrevState).toEqual(cduCurrentState);\n    });\n\n    it('prevState argument should be a different object if state does change', () => {\n      let updateState;\n      let cduPrevState;\n      let cduCurrentState;\n\n      interface FooState {\n        value: number;\n      }\n\n      class Foo extends Component<unknown, FooState> {\n        public state: FooState;\n        constructor() {\n          super();\n          this.state = { value: 0 };\n          updateState = this.updateState.bind(this);\n        }\n\n        public updateState() {\n          const value = (this.state.value + 1) % 2;\n          this.setState({\n            value,\n          });\n        }\n\n        public componentDidUpdate(_prevProps, prevState) {\n          cduPrevState = prevState;\n          cduCurrentState = this.state;\n        }\n\n        public render() {\n          return <div>{this.state.value}</div>;\n        }\n      }\n\n      render(<Foo />, container);\n\n      updateState();\n      rerender();\n\n      expect(cduPrevState).not.toEqual(cduCurrentState);\n    });\n\n    it(\"prevProps argument should be the same object if props don't change\", () => {\n      let updateState;\n      let cduPrevProps;\n      let cduCurrentProps;\n\n      interface FooState {\n        value: number;\n      }\n\n      class Foo extends Component<unknown, FooState> {\n        public state: FooState;\n        constructor() {\n          super();\n          this.state = { value: 0 };\n          updateState = this.updateState.bind(this);\n        }\n\n        public updateState() {\n          const value = (this.state.value + 1) % 2;\n          this.setState({\n            value,\n          });\n        }\n\n        public componentDidUpdate(prevProps) {\n          cduPrevProps = prevProps;\n          cduCurrentProps = this.props;\n        }\n\n        public render() {\n          return <div>{this.state.value}</div>;\n        }\n      }\n\n      render(<Foo />, container);\n\n      updateState();\n      rerender();\n\n      expect(cduPrevProps).toEqual(cduCurrentProps);\n    });\n\n    it('prevProps argument should be a different object if props do change', () => {\n      let changeProps;\n      let cduPrevProps;\n      let cduCurrentProps;\n\n      interface PropsProviderState {\n        value: number;\n      }\n\n      class PropsProvider extends Component<unknown, PropsProviderState> {\n        public state: PropsProviderState;\n\n        constructor() {\n          super();\n          this.state = { value: 0 };\n          changeProps = this.changeReceiverProps.bind(this);\n        }\n\n        public changeReceiverProps() {\n          const value = (this.state.value + 1) % 2;\n          this.setState({\n            value,\n          });\n        }\n\n        public render() {\n          return <PropsReceiver value={this.state.value} />;\n        }\n      }\n\n      interface PropsReceiverProps {\n        value: number;\n      }\n\n      class PropsReceiver extends Component<PropsReceiverProps> {\n        public componentDidUpdate(prevProps) {\n          cduPrevProps = prevProps;\n          cduCurrentProps = this.props;\n        }\n\n        public render({ value }) {\n          return <div>{value}</div>;\n        }\n      }\n\n      render(<PropsProvider />, container);\n\n      changeProps();\n      rerender();\n\n      expect(cduPrevProps).not.toEqual(cduCurrentProps);\n    });\n  });\n\n  describe('#constructor and component(Did|Will)(Mount|Unmount)', () => {\n    let setState;\n\n    interface OuterState {\n      show: boolean;\n    }\n\n    class Outer extends Component<any, OuterState> {\n      constructor(p, c) {\n        super(p, c);\n        this.state = { show: true };\n        setState = (s) => {\n          this.setState(s);\n        };\n      }\n\n      public render(props, { show }) {\n        return <div>{show && <Inner {...props} />}</div>;\n      }\n    }\n\n    class LifecycleTestComponent extends Component {\n      constructor(p, c) {\n        super(p, c);\n        this._constructor();\n      }\n\n      public _constructor() {}\n\n      public componentWillMount() {}\n\n      public componentDidMount() {}\n\n      public componentWillUnmount() {}\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    class Inner extends LifecycleTestComponent {\n      public render() {\n        return (\n          <div>\n            <InnerMost />\n          </div>\n        );\n      }\n    }\n\n    class InnerMost extends LifecycleTestComponent {\n      public render() {\n        return <div />;\n      }\n    }\n\n    describe('inner components', () => {\n      let constructorSpy: jasmine.Spy;\n      let willMountSpy: jasmine.Spy;\n      let didMountSpy: jasmine.Spy;\n      let willUnmountSpy: jasmine.Spy;\n\n      const reset = () => {\n        constructorSpy.calls.reset();\n        willMountSpy.calls.reset();\n        didMountSpy.calls.reset();\n        willUnmountSpy.calls.reset();\n      };\n\n      beforeEach(function () {\n        constructorSpy = spyOn(Inner.prototype, '_constructor');\n        willMountSpy = spyOn(Inner.prototype, 'componentWillMount');\n        didMountSpy = spyOn(Inner.prototype, 'componentDidMount');\n        willUnmountSpy = spyOn(Inner.prototype, 'componentWillUnmount');\n      });\n\n      it('should be invoked for components on initial render', () => {\n        reset();\n        render(<Outer />, container);\n        expect(constructorSpy.calls.count()).toBe(1);\n        expect(didMountSpy.calls.count()).toBe(1);\n        expect(willMountSpy.calls.count()).toBe(1);\n      });\n\n      it('should be invoked for components on unmount', () => {\n        reset();\n        render(<Outer />, container);\n        setState({ show: false });\n        rerender();\n\n        expect(willUnmountSpy.calls.count()).toBe(1);\n      });\n\n      it('should be invoked for components on re-render', () => {\n        reset();\n        render(<Outer />, container);\n        setState({ show: true });\n        rerender();\n\n        expect(constructorSpy.calls.count()).toBe(1);\n        expect(didMountSpy.calls.count()).toBe(1);\n        expect(willMountSpy.calls.count()).toBe(1);\n      });\n    });\n\n    describe('innermost components', () => {\n      let constructorSpy: jasmine.Spy;\n      let willMountSpy: jasmine.Spy;\n      let didMountSpy: jasmine.Spy;\n      let willUnmountSpy: jasmine.Spy;\n\n      const reset = () => {\n        constructorSpy.calls.reset();\n        willMountSpy.calls.reset();\n        didMountSpy.calls.reset();\n        willUnmountSpy.calls.reset();\n      };\n\n      beforeEach(function () {\n        constructorSpy = spyOn(InnerMost.prototype, '_constructor');\n        willMountSpy = spyOn(InnerMost.prototype, 'componentWillMount');\n        didMountSpy = spyOn(InnerMost.prototype, 'componentDidMount');\n        willUnmountSpy = spyOn(InnerMost.prototype, 'componentWillUnmount');\n      });\n\n      it('should be invoked for components on initial render', () => {\n        reset();\n        render(<Outer />, container);\n        expect(constructorSpy.calls.count()).toBe(1);\n        expect(willMountSpy.calls.count()).toBe(1);\n        expect(didMountSpy.calls.count()).toBe(1);\n      });\n\n      it('should be invoked for components on unmount', () => {\n        reset();\n        render(<Outer />, container);\n        setState({ show: false });\n        rerender();\n\n        expect(willUnmountSpy.calls.count()).toBe(1);\n      });\n\n      it('should be invoked for components on re-render', () => {\n        reset();\n        render(<Outer />, container);\n        setState({ show: true });\n        rerender();\n\n        expect(constructorSpy.calls.count()).toBe(1);\n        expect(willMountSpy.calls.count()).toBe(1);\n        expect(didMountSpy.calls.count()).toBe(1);\n      });\n    });\n\n    describe('when shouldComponentUpdate() returns false', () => {\n      let outerSetState;\n\n      interface Outer1State {\n        show: boolean;\n      }\n\n      class Outer1 extends Component<any, Outer1State> {\n        constructor() {\n          super();\n          this.state = { show: true };\n          outerSetState = (s) => {\n            this.setState(s);\n          };\n        }\n\n        public render(props, { show }) {\n          return (\n            <div>\n              {show && (\n                <div>\n                  <Inner1 {...props} />\n                </div>\n              )}\n            </div>\n          );\n        }\n      }\n\n      class Inner1 extends Component {\n        public shouldComponentUpdate() {\n          return false;\n        }\n\n        public componentWillMount() {}\n\n        public componentDidMount() {}\n\n        public componentWillUnmount() {}\n\n        public render() {\n          return <div />;\n        }\n      }\n\n      let willMountSpy: jasmine.Spy;\n      let didMountSpy: jasmine.Spy;\n      let willUnmountSpy: jasmine.Spy;\n\n      beforeEach(function () {\n        willMountSpy = spyOn(Inner1.prototype, 'componentWillMount');\n        didMountSpy = spyOn(Inner1.prototype, 'componentDidMount');\n        willUnmountSpy = spyOn(Inner1.prototype, 'componentWillUnmount');\n      });\n\n      it('should be invoke normally on initial mount', () => {\n        render(<Outer1 />, container);\n        expect(willMountSpy.calls.count()).toBe(1);\n        expect(didMountSpy.calls.count()).toBe(1);\n      });\n\n      it('should be invoked normally on unmount', () => {\n        render(<Outer1 />, container);\n        outerSetState({ show: false });\n        rerender();\n\n        expect(willUnmountSpy.calls.count()).toBe(1);\n      });\n\n      it('should still invoke mount for shouldComponentUpdate():false', () => {\n        render(<Outer1 />, container);\n        outerSetState({ show: true });\n        rerender();\n\n        expect(willMountSpy.calls.count()).toBe(1);\n        expect(didMountSpy.calls.count()).toBe(1);\n      });\n\n      it('should still invoke unmount for shouldComponentUpdate():false', () => {\n        render(<Outer1 />, container);\n        outerSetState({ show: false });\n        rerender();\n\n        expect(willUnmountSpy.calls.count()).toBe(1);\n      });\n    });\n  });\n\n  describe('#shouldComponentUpdate', () => {\n    interface ShouldState {\n      show: boolean;\n    }\n\n    let setState;\n    let renderSpy: jasmine.Spy;\n    let shouldUpdateSpy: jasmine.Spy;\n\n    class Should extends Component<unknown, ShouldState> {\n      constructor() {\n        super();\n        this.state = { show: true };\n        setState = (s) => {\n          this.setState(s);\n        };\n      }\n\n      public render(_props, { show }) {\n        return show ? <div /> : null;\n      }\n    }\n\n    class ShouldNot extends Should {\n      public shouldComponentUpdate() {\n        return false;\n      }\n    }\n\n    beforeEach(function () {\n      renderSpy = spyOn(Should.prototype, 'render');\n      shouldUpdateSpy = spyOn(ShouldNot.prototype, 'shouldComponentUpdate');\n    });\n\n    it('should rerender component on change by default', () => {\n      render(<Should />, container);\n      setState({ show: false });\n      rerender();\n\n      expect(renderSpy.calls.count()).toBe(2);\n    });\n\n    it('should not rerender component if shouldComponentUpdate returns false', () => {\n      render(<ShouldNot />, container);\n      setState({ show: false });\n      rerender();\n\n      expect(shouldUpdateSpy.calls.count()).toBe(1);\n      expect(renderSpy.calls.count()).toBe(1);\n    });\n\n    it('should be passed next props and state', () => {\n      let updateState;\n      let curProps;\n      let curState;\n      let nextPropsArg;\n      let nextStateArg;\n\n      interface FooState {\n        value: number;\n      }\n\n      class Foo extends Component<{ foo: string }, FooState> {\n        public state: FooState;\n        constructor(props) {\n          super(props);\n          this.state = {\n            value: 0,\n          };\n          updateState = () => {\n            this.setState({\n              value: this.state.value + 1,\n            });\n          };\n        }\n\n        public static getDerivedStateFromProps(_props, state) {\n          // NOTE: Don't do this in real production code!\n          // https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html\n          return {\n            value: state.value + 1,\n          };\n        }\n\n        public shouldComponentUpdate(nextProps, nextState) {\n          nextPropsArg = { ...nextProps };\n          nextStateArg = { ...nextState };\n\n          curProps = { ...this.props };\n          curState = { ...this.state };\n\n          return true;\n        }\n\n        public render() {\n          return <div>{this.state.value}</div>;\n        }\n      }\n\n      // Expectation:\n      // `this.state` in shouldComponentUpdate should be\n      // the state before setState or getDerivedStateFromProps was called\n      // `nextState` in shouldComponentUpdate should be\n      // the updated state after getDerivedStateFromProps was called\n\n      // Initial render\n      // state.value: initialized to 0 in constructor, 0 -> 1 in gDSFP\n      render(<Foo foo=\"foo\" />, container);\n      expect(container.firstChild.textContent).toEqual('1');\n      expect(curProps).toBeUndefined();\n      expect(curState).toBeUndefined();\n      expect(nextPropsArg).toBeUndefined();\n      expect(nextStateArg).toBeUndefined();\n\n      // New props\n      // state.value: 1 -> 2 in gDSFP\n      render(<Foo foo=\"bar\" />, container);\n      expect(container.firstChild.textContent).toEqual('2');\n      expect(curProps).toEqual({\n        foo: 'foo',\n      });\n      expect(curState).toEqual({\n        value: 1,\n      });\n      expect(nextPropsArg).toEqual({\n        foo: 'bar',\n      });\n      expect(nextStateArg).toEqual({\n        value: 2,\n      });\n\n      // New state\n      // state.value: 2 -> 3 in updateState, 3\n      updateState();\n      expect(container.firstChild.textContent).toEqual('4');\n      expect(curProps).toEqual({\n        foo: 'bar',\n      });\n      expect(curState).toEqual({\n        value: 2,\n      });\n      expect(nextPropsArg).toEqual({\n        foo: 'bar',\n      });\n      expect(nextStateArg).toEqual({\n        value: 4,\n      });\n    });\n  });\n\n  describe('#setState', () => {\n    it('should NOT mutate state, only create new versions', (done) => {\n      const stateConstant = {};\n      let didMount = false;\n      let componentState;\n\n      class Stateful extends Component {\n        constructor() {\n          super(...arguments);\n          this.state = stateConstant;\n        }\n\n        public componentDidMount() {\n          didMount = true;\n          this.setState({ key: 'value' }, () => {\n            componentState = this.state;\n          });\n        }\n      }\n\n      render(<Stateful />, container);\n      rerender();\n\n      expect(didMount).toEqual(true);\n\n      setTimeout(() => {\n        expect(componentState).toEqual({ key: 'value' });\n        expect(stateConstant).toEqual({});\n        done();\n      }, 10);\n    });\n  });\n\n  describe('Lifecycle DOM Timing', () => {\n    it('should render in a single microtask', () => {\n      interface CounterState {\n        count: number;\n      }\n\n      class Counter extends Component<unknown, CounterState> {\n        constructor() {\n          super();\n          this.state = { count: 0 };\n        }\n\n        public render(_props, { count }) {\n          if (count < 5) {\n            this.setState({ count: count + 1 });\n          }\n          return count;\n        }\n      }\n\n      render(<Counter />, container);\n\n      rerender();\n      expect(container.textContent).toEqual('5');\n    });\n\n    it('should be invoked when dom does (DidMount, WillUnmount) or does not (WillMount, DidUnmount) exist', () => {\n      let setState;\n\n      interface Outer1State {\n        show: boolean;\n      }\n\n      class Outer extends Component<unknown, Outer1State> {\n        constructor() {\n          super();\n          this.state = { show: true };\n          setState = (s) => {\n            this.setState(s);\n          };\n        }\n\n        public componentWillMount() {\n          expect(document.getElementById('OuterDiv')).toBeNull();\n        }\n\n        public componentDidMount() {\n          expect(document.getElementById('OuterDiv')).not.toBeNull();\n        }\n\n        public componentWillUnmount() {\n          expect(document.getElementById('OuterDiv')).not.toBeNull();\n        }\n\n        public render(props, { show }) {\n          return (\n            <div id=\"OuterDiv\">\n              {show && (\n                <div>\n                  <Inner {...props} />\n                </div>\n              )}\n            </div>\n          );\n        }\n      }\n\n      class Inner extends Component {\n        public componentWillMount() {\n          expect(document.getElementById('InnerDiv')).toBeNull();\n        }\n\n        public componentDidMount() {\n          expect(document.getElementById('InnerDiv')).not.toBeNull();\n        }\n\n        public componentWillUnmount() {\n          expect(document.getElementById('InnerDiv')).not.toBeNull();\n        }\n\n        public render() {\n          return <div id=\"InnerDiv\" />;\n        }\n      }\n\n      const proto = Inner.prototype;\n      const orderOfCalls: string[] = [];\n\n      const willMountSpy = spyOn(proto, 'componentWillMount').and.callFake(\n        function () {\n          orderOfCalls.push('willMount');\n        },\n      );\n      const didMountSpy = spyOn(proto, 'componentDidMount').and.callFake(\n        function () {\n          orderOfCalls.push('didMount');\n        },\n      );\n      const unmountSpy = spyOn(proto, 'componentWillUnmount').and.callFake(\n        function () {\n          orderOfCalls.push('willUnmount');\n        },\n      );\n\n      const reset = () => {\n        willMountSpy.calls.reset();\n        didMountSpy.calls.reset();\n        unmountSpy.calls.reset();\n      };\n\n      render(<Outer />, container);\n      expect(willMountSpy.calls.count()).toBe(1);\n      expect(didMountSpy.calls.count()).toBe(1);\n\n      expect(orderOfCalls).toEqual(['willMount', 'didMount']);\n\n      reset();\n      setState({ show: false });\n\n      expect(document.getElementById('InnerDiv')).toBeNull();\n\n      expect(unmountSpy.calls.count()).toBe(1);\n\n      reset();\n      setState({ show: true });\n\n      expect(document.getElementById('InnerDiv')).not.toBeNull();\n\n      expect(willMountSpy.calls.count()).toBe(1);\n      expect(didMountSpy.calls.count()).toBe(1);\n\n      expect(orderOfCalls).toEqual([\n        'willMount',\n        'didMount',\n        'willUnmount',\n        'willMount',\n        'didMount',\n      ]);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/patching-jsx.spec.tsx",
    "content": "import { Component, type InfernoNode, render, rerender } from 'inferno';\n\ndescribe('patching routine (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should always unmount/mount if ReCreate flag is set', () => {\n    const spyObj = { fn: () => {} };\n    const spyObj2 = { fn: () => {} };\n    const spy1 = spyOn(spyObj, 'fn');\n    const spy2 = spyOn(spyObj2, 'fn');\n\n    const div = (\n      <div $ReCreate ref={spy1}>\n        1\n      </div>\n    );\n\n    render(div, container);\n\n    const firstDiv = container.firstChild;\n\n    expect(container.innerHTML).toEqual('<div>1</div>');\n    expect(spy1.calls.count()).toBe(1);\n    expect(spy1.calls.argsFor(0).length).toBe(1);\n    expect(spy1.calls.argsFor(0)[0]).toEqual(firstDiv);\n\n    const div2 = (\n      <div $ReCreate ref={spy2}>\n        1\n      </div>\n    );\n\n    render(div2, container);\n\n    expect(firstDiv).not.toBe(container.firstChild); // Div is different\n\n    // Html is the same\n    expect(container.innerHTML).toEqual('<div>1</div>');\n\n    // Verify all callbacks were called\n    expect(spy1.calls.count()).toBe(2);\n    expect(spy1.calls.argsFor(1).length).toBe(1);\n    expect(spy1.calls.argsFor(1)[0]).toEqual(null);\n\n    expect(spy2.calls.count()).toBe(1);\n    expect(spy2.calls.argsFor(0).length).toBe(1);\n    expect(spy2.calls.argsFor(0)[0]).toEqual(container.firstChild);\n  });\n\n  it('Should be able to patch references', () => {\n    interface Component1State {\n      value: number;\n    }\n\n    class Component1 extends Component<unknown, Component1State> {\n      public state: Component1State;\n\n      constructor(p, c) {\n        super(p, c);\n\n        this.state = {\n          value: 1,\n        };\n\n        this.add = this.add.bind(this);\n      }\n\n      public add(e) {\n        e.stopPropagation();\n\n        this.setState({\n          value: this.state.value + 1,\n        });\n      }\n\n      public render(props) {\n        return (\n          <div id=\"child\" onclick={this.add}>\n            <span>{this.state.value}</span>\n            {props.children}\n          </div>\n        );\n      }\n    }\n\n    interface ParentState {\n      value: number;\n    }\n\n    class Parent extends Component<unknown, ParentState> {\n      public state: ParentState;\n      constructor(p, c) {\n        super(p, c);\n\n        this.state = {\n          value: 1,\n        };\n\n        this.add = this.add.bind(this);\n      }\n\n      public add(e) {\n        e.stopPropagation();\n\n        this.setState({\n          value: 3,\n        });\n      }\n\n      public render() {\n        const arr: InfernoNode[] = [];\n\n        arr.push(<div>{this.state.value}</div>);\n\n        if (this.state.value > 1) {\n          arr.unshift(<div>{this.state.value}</div>);\n        }\n\n        return (\n          <div id=\"parent\" onclick={this.add}>\n            <Component1>\n              <div $HasNonKeyedChildren>{arr}</div>\n            </Component1>\n          </div>\n        );\n      }\n    }\n\n    render(<Parent />, container);\n\n    expect(container.innerHTML).toBe(\n      '<div id=\"parent\"><div id=\"child\"><span>1</span><div><div>1</div></div></div></div>',\n    );\n\n    container.querySelector('#child').click();\n    rerender();\n\n    expect(container.innerHTML).toBe(\n      '<div id=\"parent\"><div id=\"child\"><span>2</span><div><div>1</div></div></div></div>',\n    );\n\n    container.querySelector('#parent').click();\n    rerender();\n\n    expect(container.innerHTML).toBe(\n      '<div id=\"parent\"><div id=\"child\"><span>2</span><div><div>3</div><div>3</div></div></div></div>',\n    );\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/patching.spec.tsx",
    "content": "import {\n  Component,\n  createTextVNode,\n  createVNode,\n  linkEvent,\n  render,\n} from 'inferno';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\n\ndescribe('patching routine', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should do nothing if lastVNode strictly equals nextVnode', () => {\n    const yar = createVNode(\n      VNodeFlags.HtmlElement,\n      'div',\n      null,\n      createTextVNode('123'),\n      ChildFlags.HasVNodeChildren,\n      null,\n      null,\n      null,\n    );\n    const bar = createVNode(\n      VNodeFlags.HtmlElement,\n      'div',\n      null,\n      createTextVNode('123'),\n      ChildFlags.HasVNodeChildren,\n      null,\n      null,\n      null,\n    );\n    let foo = createVNode(\n      VNodeFlags.HtmlElement,\n      'div',\n      null,\n      [bar, yar],\n      ChildFlags.HasNonKeyedChildren,\n      null,\n      null,\n      null,\n    );\n\n    render(foo, container);\n    expect(container.innerHTML).toEqual(\n      '<div><div>123</div><div>123</div></div>',\n    );\n\n    foo = createVNode(\n      VNodeFlags.HtmlElement,\n      'div',\n      null,\n      [bar, yar],\n      ChildFlags.HasNonKeyedChildren,\n      null,\n      null,\n      null,\n    );\n\n    render(foo, container);\n    expect(container.innerHTML).toEqual(\n      '<div><div>123</div><div>123</div></div>',\n    );\n  });\n\n  it('Should mount nextNode if lastNode crashed', () => {\n    const validNode = createVNode(\n      VNodeFlags.HtmlElement,\n      'span',\n      null,\n      createTextVNode('a'),\n      ChildFlags.HasVNodeChildren,\n      null,\n      null,\n      null,\n    );\n    const invalidNode = createVNode(0, 'span');\n\n    render(validNode, container);\n    try {\n      render(invalidNode, container);\n    } catch (e) {\n      expect(\n        e.message.includes('Inferno Error: mount() received an object'),\n      ).toBeTruthy();\n    }\n    expect(container.innerHTML).toEqual('<span>a</span>');\n\n    render(validNode, container);\n    expect(container.innerHTML).toEqual('<span>a</span>');\n  });\n\n  it('Should not access real DOM property when text does not change', () => {\n    render(createTextVNode('a'), container);\n    expect(container.innerHTML).toEqual('a');\n    render(createTextVNode('a'), container);\n    expect(container.innerHTML).toEqual('a');\n  });\n\n  it('Should not patch same innerHTML', () => {\n    container.innerHTML = '<span><span><span>child</span></span></span>';\n\n    const childelem = container.firstElementChild.firstElementChild;\n    const props = { dangerouslySetInnerHTML: { __html: '<span>child</span>' } };\n\n    const bar = createVNode(\n      VNodeFlags.HtmlElement,\n      'span',\n      null,\n      null,\n      ChildFlags.HasInvalidChildren,\n      props,\n      null,\n      null,\n    );\n    const foo = createVNode(\n      VNodeFlags.HtmlElement,\n      'span',\n      null,\n      [bar],\n      ChildFlags.HasNonKeyedChildren,\n      null,\n      null,\n      null,\n    );\n\n    render(foo, container);\n\n    expect(childelem).toBe(container.firstElementChild.firstElementChild);\n  });\n\n  it('Should always unmount/mount if ReCreate flag is set', () => {\n    const spyObj = { fn: () => {} };\n    const spyObj2 = { fn: () => {} };\n    const spy1 = spyOn(spyObj, 'fn');\n    const spy2 = spyOn(spyObj2, 'fn');\n\n    const div = createVNode(\n      VNodeFlags.HtmlElement | VNodeFlags.ReCreate,\n      'div',\n      null,\n      createTextVNode('1'),\n      ChildFlags.HasVNodeChildren,\n      null,\n      null,\n      spy1,\n    );\n\n    render(div, container);\n\n    const firstDiv = container.firstChild;\n\n    expect(container.innerHTML).toEqual('<div>1</div>');\n    expect(spy1.calls.count()).toBe(1);\n    expect(spy1.calls.argsFor(0).length).toBe(1);\n    expect(spy1.calls.argsFor(0)[0]).toEqual(firstDiv);\n\n    const div2 = createVNode(\n      VNodeFlags.HtmlElement | VNodeFlags.ReCreate,\n      'div',\n      null,\n      createTextVNode('1'),\n      ChildFlags.HasVNodeChildren,\n      null,\n      null,\n      spy2,\n    );\n\n    render(div2, container);\n\n    expect(firstDiv).not.toBe(container.firstChild); // Div is different\n\n    // Html is the same\n    expect(container.innerHTML).toEqual('<div>1</div>');\n\n    // Verify all callbacks were called\n    expect(spy1.calls.count()).toBe(2);\n    expect(spy1.calls.argsFor(1).length).toBe(1);\n    expect(spy1.calls.argsFor(1)[0]).toEqual(null);\n\n    expect(spy2.calls.count()).toBe(1);\n    expect(spy2.calls.argsFor(0).length).toBe(1);\n    expect(spy2.calls.argsFor(0)[0]).toEqual(container.firstChild);\n  });\n\n  it('Should not mutate previous children', () => {\n    let callCount = 0;\n\n    class Collapsible extends Component {\n      public render() {\n        return (\n          <div>\n            <button\n              onClick={() => {\n                callCount++;\n                this.setState({});\n              }}\n            >\n              Click twice !\n            </button>\n            {this.props.children}\n          </div>\n        );\n      }\n    }\n\n    class Clock extends Component {\n      public render() {\n        return (\n          <Collapsible>\n            <div>\n              {[<p>Hello 0</p>, <p>Hello 1</p>]}\n              <strong>Hello 2</strong>\n            </div>\n            <p>Hello 3</p>\n          </Collapsible>\n        );\n      }\n    }\n\n    const expectedDOM =\n      '<div><button>Click twice !</button><div><p>Hello 0</p><p>Hello 1</p><strong>Hello 2</strong></div><p>Hello 3</p></div>';\n\n    render(<Clock />, container);\n\n    expect(container.innerHTML).toBe(expectedDOM);\n\n    const btn = container.querySelector('button');\n\n    btn.click();\n\n    expect(callCount).toBe(1);\n\n    expect(container.innerHTML).toBe(expectedDOM);\n\n    btn.click();\n\n    expect(callCount).toBe(2);\n\n    expect(container.innerHTML).toBe(expectedDOM);\n\n    btn.click();\n\n    expect(callCount).toBe(3);\n\n    expect(container.innerHTML).toBe(expectedDOM);\n\n    btn.click();\n\n    expect(callCount).toBe(4);\n\n    expect(container.innerHTML).toBe(expectedDOM);\n  });\n\n  it('Should not re-mount hoisted vNode', () => {\n    const Com1 = () => <div>1</div>;\n    const Com2 = () => <div>2</div>;\n\n    const div = (\n      <div>\n        <Com1 />\n        <Com2 />\n      </div>\n    );\n\n    function Comp() {\n      return div;\n    }\n\n    render(<Comp />, container);\n\n    expect(container.innerHTML).toBe('<div><div>1</div><div>2</div></div>');\n\n    const first = container.firstChild.childNodes[0];\n    const second = container.firstChild.childNodes[1];\n\n    render(<Comp />, container);\n\n    expect(container.innerHTML).toBe('<div><div>1</div><div>2</div></div>');\n\n    const first2 = container.firstChild.childNodes[0];\n    const second2 = container.firstChild.childNodes[1];\n\n    // Verify dom nodes did not change\n    expect(first).toBe(first2);\n    expect(second).toBe(second2);\n\n    render(<Comp />, container);\n\n    expect(container.innerHTML).toBe('<div><div>1</div><div>2</div></div>');\n\n    const first3 = container.firstChild.childNodes[0];\n    const second3 = container.firstChild.childNodes[1];\n\n    // Verify dom nodes did not change\n    expect(first).toBe(first3);\n    expect(second).toBe(second3);\n  });\n\n  describe('Event changes', () => {\n    describe('Synthetic', () => {\n      it('Should remove function if next is boolean (false)', () => {\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onClick={linkObj.methodFn} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        render(<div onClick={false as any} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        // ADD BACK\n\n        render(<div onclick={linkObj.methodFn} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(2);\n      });\n\n      it('Should remove function if next is boolean (true)', () => {\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onClick={linkObj.methodFn} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        render(<div onClick={true as any} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        // ADD BACK\n\n        render(<div onclick={linkObj.methodFn} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(2);\n      });\n\n      it('Should remove linkEvent if next is boolean (false)', () => {\n        const data = { foo: 1 };\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onClick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        render(<div onClick={false as any} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        // ADD BACK\n\n        render(<div onClick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(2);\n      });\n\n      it('Should remove linkEvent if next is boolean (true)', () => {\n        const data = { foo: 1 };\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onClick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        render(<div onClick={true as any} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        // ADD BACK\n\n        render(<div onClick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(2);\n      });\n\n      it('Should change from LinkEvent to Function', () => {\n        const data = { foo: 1 };\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onClick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        const anotherObj = {\n          anotherFn() {},\n        };\n        spyOn(anotherObj, 'anotherFn');\n\n        render(<div onClick={anotherObj.anotherFn} />, container);\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n      });\n\n      it('Should change from Function to LinkEvent', () => {\n        const anotherObj = {\n          anotherFn() {},\n        };\n        spyOn(anotherObj, 'anotherFn');\n\n        render(<div onClick={anotherObj.anotherFn} />, container);\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n\n        const data = { foo: 1 };\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onClick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n      });\n\n      it('Should change from Function to different Function', () => {\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onClick={linkObj.methodFn} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        const anotherObj = {\n          anotherFn() {},\n        };\n        spyOn(anotherObj, 'anotherFn');\n\n        render(<div onClick={anotherObj.anotherFn} />, container);\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n      });\n\n      it('Should change from LinkEvent fn to different LinkEvent fn', () => {\n        const data = { foo: 1 };\n        const anotherObj = {\n          anotherFn() {},\n        };\n        spyOn(anotherObj, 'anotherFn');\n\n        render(\n          <div onClick={linkEvent(data, anotherObj.anotherFn)} />,\n          container,\n        );\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onClick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n      });\n\n      it('Should change from LinkEvent data to different LinkEvent data', () => {\n        const obj1 = { foo: 1 };\n        const obj2 = { foo: 2 };\n        let secondArg = null;\n\n        const anotherObj = {\n          anotherFn(_, ev) {\n            secondArg = ev;\n          },\n        };\n\n        const anotherFnSpy = spyOn(anotherObj, 'anotherFn').and.callThrough();\n\n        render(<div onClick={linkEvent(obj1, anotherFnSpy)} />, container);\n\n        expect(anotherFnSpy).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherFnSpy).toHaveBeenCalledTimes(1);\n        expect(anotherFnSpy).toHaveBeenCalledWith(obj1, secondArg);\n\n        anotherFnSpy.calls.reset();\n\n        render(<div onClick={linkEvent(obj2, anotherFnSpy)} />, container);\n\n        expect(anotherFnSpy).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherFnSpy).toHaveBeenCalledTimes(1);\n        expect(anotherFnSpy).toHaveBeenCalledWith(obj2, secondArg);\n      });\n    });\n\n    describe('Regular', () => {\n      it('Should remove function if next is boolean (false)', () => {\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onclick={linkObj.methodFn} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        render(<div onclick={false as any} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        // ADD BACK\n\n        render(<div onclick={linkObj.methodFn} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(2);\n      });\n\n      it('Should remove function if next is boolean (true)', () => {\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onclick={linkObj.methodFn} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        render(<div onclick={true as any} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        // ADD BACK\n\n        render(<div onclick={linkObj.methodFn} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(2);\n      });\n\n      it('Should remove linkEvent if next is boolean (false)', () => {\n        const data = { foo: 1 };\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onclick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        render(<div onclick={false as any} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        // ADD BACK\n\n        render(<div onclick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(2);\n      });\n\n      it('Should remove linkEvent if next is boolean (true)', () => {\n        const data = { foo: 1 };\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onclick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        render(<div onclick={true as any} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        // ADD BACK\n\n        render(<div onclick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(2);\n      });\n\n      it('Should change from LinkEvent to Function', () => {\n        const data = { foo: 1 };\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onclick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        const anotherObj = {\n          anotherFn() {},\n        };\n        spyOn(anotherObj, 'anotherFn');\n\n        render(<div onclick={anotherObj.anotherFn} />, container);\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n      });\n\n      it('Should change from Function to LinkEvent', () => {\n        const anotherObj = {\n          anotherFn() {},\n        };\n        spyOn(anotherObj, 'anotherFn');\n\n        render(<div onclick={anotherObj.anotherFn} />, container);\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n\n        const data = { foo: 1 };\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onclick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n      });\n\n      it('Should change from Function to different Function', () => {\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onclick={linkObj.methodFn} />, container);\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n\n        const anotherObj = {\n          anotherFn() {},\n        };\n        spyOn(anotherObj, 'anotherFn');\n\n        render(<div onclick={anotherObj.anotherFn} />, container);\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n      });\n\n      it('Should replace old input and input dirty value', () => {\n        const input = v => <input type=\"text\" key={v} id={v} defaultValue={v} />;\n\n        render(input('start'), container);\n        expect(container.firstChild.value).toBe('start');\n        expect(container.innerHTML).toBe('<input type=\"text\" id=\"start\" value=\"start\">')\n\n        render(input('end'), container);\n        expect(container.innerHTML).toBe('<input type=\"text\" id=\"end\" value=\"end\">')\n        expect(container.firstChild.value).toBe('end');\n      });\n\n      it('Should replace old input and input dirty value, after change', () => {\n        const input = v => <input type=\"text\" key={v} id={v} defaultValue={v} />;\n\n        render(input('start'), container);\n        expect(container.firstChild.value).toBe('start');\n        expect(container.innerHTML).toBe('<input type=\"text\" id=\"start\" value=\"start\">')\n\n        container.firstChild.value = 'changed';\n\n        render(input('end'), container);\n        expect(container.innerHTML).toBe('<input type=\"text\" id=\"end\" value=\"end\">')\n        expect(container.firstChild.value).toBe('end');\n      });\n\n      it('Should change from LinkEvent fn to different LinkEvent fn', () => {\n        const data = { foo: 1 };\n        const anotherObj = {\n          anotherFn() {},\n        };\n        spyOn(anotherObj, 'anotherFn');\n\n        render(\n          <div onclick={linkEvent(data, anotherObj.anotherFn)} />,\n          container,\n        );\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n\n        const linkObj = {\n          methodFn() {},\n        };\n        spyOn(linkObj, 'methodFn');\n\n        render(<div onclick={linkEvent(data, linkObj.methodFn)} />, container);\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherObj.anotherFn).toHaveBeenCalledTimes(1);\n        expect(linkObj.methodFn).toHaveBeenCalledTimes(1);\n      });\n\n      it('Should change from LinkEvent data to different LinkEvent data', () => {\n        const obj1 = { foo: 1 };\n        const obj2 = { foo: 2 };\n        let secondArg = null;\n\n        const anotherObj = {\n          anotherFn(_, ev) {\n            secondArg = ev;\n          },\n        };\n\n        const anotherFnSpy = spyOn(anotherObj, 'anotherFn').and.callThrough();\n\n        render(<div onclick={linkEvent(obj1, anotherFnSpy)} />, container);\n\n        expect(anotherFnSpy).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherFnSpy).toHaveBeenCalledTimes(1);\n        expect(anotherFnSpy).toHaveBeenCalledWith(obj1, secondArg);\n\n        anotherFnSpy.calls.reset();\n\n        render(<div onclick={linkEvent(obj2, anotherFnSpy)} />, container);\n\n        expect(anotherFnSpy).toHaveBeenCalledTimes(0);\n\n        container.firstChild.click();\n\n        expect(anotherFnSpy).toHaveBeenCalledTimes(1);\n        expect(anotherFnSpy).toHaveBeenCalledWith(obj2, secondArg);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/portal.spec.tsx",
    "content": "import {\n  Component,\n  createPortal,\n  InfernoNode,\n  render as _render,\n} from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\ndescribe('Portal spec', () => {\n  let container;\n\n  function render(input, $container, cb?) {\n    _render(input, $container, cb);\n\n    const rootInput = $container.$V;\n\n    if (rootInput && rootInput.flags & VNodeFlags.Component) {\n      return rootInput.children;\n    }\n\n    return rootInput;\n  }\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container, null);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  let svgEls;\n  let htmlEls;\n  let mathEls;\n  const expectSVG = { ref: (el) => svgEls.push(el) };\n  const expectHTML = { ref: (el) => htmlEls.push(el) };\n  const expectMath = { ref: (el) => mathEls.push(el) };\n\n  const usePortal = function (tree) {\n    return createPortal(tree, document.createElement('div'));\n  };\n\n  const assertNamespacesMatch = function (tree) {\n    svgEls = [];\n    htmlEls = [];\n    mathEls = [];\n\n    render(tree, container);\n    for (const el of svgEls) {\n      expect(el.namespaceURI).toBe('http://www.w3.org/2000/svg');\n    }\n    for (const el of htmlEls) {\n      expect(el.namespaceURI).toBe('http://www.w3.org/1999/xhtml');\n    }\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n  };\n\n  it('should mount/unmount one portal', () => {\n    const portalContainer = document.createElement('div');\n\n    render(\n      <div>{createPortal(<div>portal</div>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<div>portal</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    render(null, container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should allow Arrays as portal content', () => {\n    const portalContainer = document.createElement('div');\n    let mountCount = 0;\n    let unmountCount = 0;\n\n    interface TesterProps {\n      children: InfernoNode;\n    }\n\n    class Tester extends Component<TesterProps> {\n      public componentWillUnmount() {\n        unmountCount++;\n      }\n\n      public componentWillMount() {\n        mountCount++;\n      }\n\n      public render({ children }: TesterProps) {\n        return children;\n      }\n    }\n\n    render(\n      createPortal(\n        [\n          <Tester key={1}>1</Tester>,\n          <Tester key={2}>2</Tester>,\n          <Tester key={3}>3</Tester>,\n        ],\n        portalContainer,\n      ),\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('123');\n    expect(container.innerHTML).toBe('');\n\n    expect(mountCount).toBe(3);\n    expect(unmountCount).toBe(0);\n\n    render(\n      createPortal(\n        [\n          <Tester key={3}>3</Tester>,\n          <Tester key={4}>4</Tester>,\n          <Tester key={1}>1</Tester>,\n        ],\n        portalContainer,\n      ),\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('341');\n    expect(container.innerHTML).toBe('');\n\n    expect(mountCount).toBe(4);\n    expect(unmountCount).toBe(1);\n\n    render(\n      createPortal(<Tester key={1}>1</Tester>, portalContainer),\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('1');\n    expect(container.innerHTML).toBe('');\n\n    expect(mountCount).toBe(5);\n    expect(unmountCount).toBe(4);\n\n    render(null, container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n\n    expect(unmountCount).toBe(5);\n  });\n\n  it('Should allow Fragments as portal content', () => {\n    const portalContainer = document.createElement('div');\n    let mountCount = 0;\n    let unmountCount = 0;\n\n    interface TesterProps {\n      children: InfernoNode;\n    }\n\n    class Tester extends Component<TesterProps> {\n      public componentWillUnmount() {\n        unmountCount++;\n      }\n\n      public componentWillMount() {\n        mountCount++;\n      }\n\n      public render({ children }: TesterProps) {\n        return children;\n      }\n    }\n\n    render(\n      createPortal(\n        // @ts-ignore\n        <>\n          <Tester key={1}>1</Tester>\n          <Tester key={2}>2</Tester>\n          <Tester key={3}>3</Tester>\n        </>,\n        portalContainer,\n      ),\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('123');\n    expect(container.innerHTML).toBe('');\n\n    expect(mountCount).toBe(3);\n    expect(unmountCount).toBe(0);\n\n    render(\n      createPortal(\n        <>\n          <Tester key={3}>3</Tester>\n          <Tester key={4}>4</Tester>\n          <Tester key={1}>1</Tester>\n        </>,\n        portalContainer,\n      ),\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('341');\n    expect(container.innerHTML).toBe('');\n\n    expect(mountCount).toBe(4);\n    expect(unmountCount).toBe(1);\n\n    render(\n      createPortal(<Tester key={1}>1</Tester>, portalContainer),\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('1');\n    expect(container.innerHTML).toBe('');\n\n    expect(mountCount).toBe(5);\n    expect(unmountCount).toBe(4);\n\n    render(null, container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n\n    expect(unmountCount).toBe(5);\n  });\n\n  it('Should mount/render/patch one portal', () => {\n    const portalContainer = document.createElement('div');\n\n    render(\n      <div>{createPortal(<div>portal</div>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<div>portal</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    // Patch\n    render(\n      <div>{createPortal(<div>portal2</div>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<div>portal2</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    // Patch Remove contents\n    render(<div>{createPortal(null, portalContainer)}</div>, container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    // Patch Add contents\n    render(\n      <div>{createPortal(<span>Fobba</span>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<span>Fobba</span>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    // Remove parent\n    render(null, container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should move portal based on container', () => {\n    const portalContainer = document.createElement('div');\n    const portalContainer2 = document.createElement('div');\n\n    render(\n      <div>{createPortal(<div>portal</div>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<div>portal</div>');\n    expect(portalContainer2.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    // Patch - change container\n    render(\n      <div>{createPortal(<div>portal2</div>, portalContainer2)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('');\n    expect(portalContainer2.innerHTML).toBe('<div>portal2</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    // Patch Remove contents of old portal - both should be removed\n    render(<div>{createPortal(null, portalContainer)}</div>, container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(portalContainer2.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    // Patch Add contents\n    render(\n      <div>{createPortal(<span>Fobba</span>, portalContainer2)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('');\n    expect(portalContainer2.innerHTML).toBe('<span>Fobba</span>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    // Remove parent\n    render(null, container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should render many portals', () => {\n    const portalContainer1 = document.createElement('div');\n    const portalContainer2 = document.createElement('div');\n\n    const ops: string[] = [];\n\n    interface ChildProps {\n      name: string;\n    }\n\n    class Child extends Component<ChildProps> {\n      public componentDidMount() {\n        ops.push(`${this.props.name} componentDidMount`);\n      }\n\n      public componentDidUpdate() {\n        ops.push(`${this.props.name} componentDidUpdate`);\n      }\n\n      public componentWillUnmount() {\n        ops.push(`${this.props.name} componentWillUnmount`);\n      }\n\n      public render() {\n        return <div>{this.props.name}</div>;\n      }\n    }\n\n    interface ParentProps {\n      step: string;\n    }\n\n    class Parent extends Component<ParentProps> {\n      public componentDidMount() {\n        ops.push(`Parent:${this.props.step} componentDidMount`);\n      }\n\n      public componentDidUpdate() {\n        ops.push(`Parent:${this.props.step} componentDidUpdate`);\n      }\n\n      public componentWillUnmount() {\n        ops.push(`Parent:${this.props.step} componentWillUnmount`);\n      }\n\n      public render() {\n        const { step } = this.props;\n\n        const portalOne = createPortal(\n          <Child key=\"b\" name={`portal1[0]:${step}`} />,\n          portalContainer1,\n        );\n\n        const portalTwo = createPortal(\n          <div>\n            <Child key=\"d\" name={`portal2[0]:${step}`} />\n            <Child key=\"e\" name={`portal2[1]:${step}`} />\n          </div>,\n          portalContainer2,\n        );\n\n        return (\n          <div>\n            <Child key=\"a\" name={`normal[0]:${step}`} />\n            {portalOne}\n            <Child key=\"c\" name={`normal[1]:${step}`} />\n            {portalTwo}\n          </div>\n        );\n      }\n    }\n\n    render(<Parent step=\"a\" />, container);\n\n    expect(portalContainer1.innerHTML).toBe('<div>portal1[0]:a</div>');\n    expect(portalContainer2.innerHTML).toBe(\n      '<div><div>portal2[0]:a</div><div>portal2[1]:a</div></div>',\n    );\n    expect(container.innerHTML).toBe(\n      '<div><div>normal[0]:a</div><div>normal[1]:a</div></div>',\n    );\n    expect(ops).toEqual([\n      'normal[0]:a componentDidMount',\n      'portal1[0]:a componentDidMount',\n      'normal[1]:a componentDidMount',\n      'portal2[0]:a componentDidMount',\n      'portal2[1]:a componentDidMount',\n      'Parent:a componentDidMount',\n    ]);\n\n    ops.length = 0;\n\n    render(<Parent step=\"b\" />, container);\n    expect(portalContainer1.innerHTML).toBe('<div>portal1[0]:b</div>');\n    expect(portalContainer2.innerHTML).toBe(\n      '<div><div>portal2[0]:b</div><div>portal2[1]:b</div></div>',\n    );\n    expect(container.innerHTML).toBe(\n      '<div><div>normal[0]:b</div><div>normal[1]:b</div></div>',\n    );\n    expect(ops).toEqual([\n      'normal[0]:b componentDidUpdate',\n      'portal1[0]:b componentDidUpdate',\n      'normal[1]:b componentDidUpdate',\n      'portal2[0]:b componentDidUpdate',\n      'portal2[1]:b componentDidUpdate',\n      'Parent:b componentDidUpdate',\n    ]);\n\n    ops.length = 0;\n    render(null, container);\n    expect(portalContainer1.innerHTML).toBe('');\n    expect(portalContainer2.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n    expect(ops).toEqual([\n      'Parent:b componentWillUnmount',\n      'normal[0]:b componentWillUnmount',\n      'portal1[0]:b componentWillUnmount',\n      'normal[1]:b componentWillUnmount',\n      'portal2[0]:b componentWillUnmount',\n      'portal2[1]:b componentWillUnmount',\n    ]);\n  });\n\n  it('should render nested portals', () => {\n    const portalContainer1 = document.createElement('div');\n    const portalContainer2 = document.createElement('div');\n    const portalContainer3 = document.createElement('div');\n\n    render(\n      <div>\n        <div key=\"a\">normal[0]</div>\n        {createPortal(\n          <div>\n            <div key=\"b\">portal1[0]</div>\n            {createPortal(<div key=\"c\">portal2[0]</div>, portalContainer2)}\n            {createPortal(<div key=\"d\">portal3[0]</div>, portalContainer3)}\n            <div key=\"e\">portal1[1]</div>\n          </div>,\n          portalContainer1,\n        )}\n        <div key=\"f\">normal[1]</div>\n      </div>,\n      container,\n    );\n    expect(portalContainer1.innerHTML).toBe(\n      '<div><div>portal1[0]</div><div>portal1[1]</div></div>',\n    );\n    expect(portalContainer2.innerHTML).toBe('<div>portal2[0]</div>');\n    expect(portalContainer3.innerHTML).toBe('<div>portal3[0]</div>');\n    expect(container.innerHTML).toBe(\n      '<div><div>normal[0]</div><div>normal[1]</div></div>',\n    );\n\n    render(null, container);\n    expect(portalContainer1.innerHTML).toBe('');\n    expect(portalContainer2.innerHTML).toBe('');\n    expect(portalContainer3.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should reconcile portal children', () => {\n    const portalContainer = document.createElement('div');\n\n    render(\n      <div>{createPortal(<div>portal:1</div>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<div>portal:1</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    render(\n      <div>{createPortal(<div>portal:2</div>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<div>portal:2</div>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    render(\n      <div>{createPortal(<p>portal:3</p>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.innerHTML).toBe('<p>portal:3</p>');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    render(\n      <div>{createPortal(<span>{['Hi', 'Bye']}</span>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.textContent).toBe('HiBye');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    render(\n      <div>{createPortal(<span>{['Bye', 'Hi']}</span>, portalContainer)}</div>,\n      container,\n    );\n    expect(portalContainer.textContent).toBe('ByeHi');\n    expect(container.innerHTML).toBe('<div></div>');\n\n    render(<div>{createPortal(null, portalContainer)}</div>, container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  it('should keep track of namespace across portals (simple)', () => {\n    assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <image {...expectSVG} />\n        {usePortal(<div {...expectHTML} />)}\n        <image {...expectSVG} />\n      </svg>,\n    );\n    assertNamespacesMatch(\n      <math {...expectMath}>\n        <mi {...expectMath} />\n        {usePortal(<div {...expectHTML} />)}\n        <mi {...expectMath} />\n      </math>,\n    );\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        <p {...expectHTML} />\n        {usePortal(\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <p {...expectHTML} />\n      </div>,\n    );\n  });\n\n  it('should keep track of namespace across portals (medium)', () => {\n    assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <image {...expectSVG} />\n        {usePortal(<div {...expectHTML} />)}\n        <image {...expectSVG} />\n        {usePortal(<div {...expectHTML} />)}\n        <image {...expectSVG} />\n      </svg>,\n    );\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        <math {...expectMath}>\n          <mi {...expectMath} />\n          {usePortal(\n            <svg {...expectSVG}>\n              <image {...expectSVG} />\n            </svg>,\n          )}\n        </math>\n        <p {...expectHTML} />\n      </div>,\n    );\n    assertNamespacesMatch(\n      <math {...expectMath}>\n        <mi {...expectMath} />\n        {usePortal(\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n            <foreignObject {...expectSVG}>\n              <p {...expectHTML} />\n              <math {...expectMath}>\n                <mi {...expectMath} />\n              </math>\n              <p {...expectHTML} />\n            </foreignObject>\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <mi {...expectMath} />\n      </math>,\n    );\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        {usePortal(\n          <svg {...expectSVG}>\n            {usePortal(<div {...expectHTML} />)}\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <p {...expectHTML} />\n      </div>,\n    );\n    assertNamespacesMatch(\n      <svg {...expectSVG}>\n        <svg {...expectSVG}>\n          {usePortal(<div {...expectHTML} />)}\n          <image {...expectSVG} />\n        </svg>\n        <image {...expectSVG} />\n      </svg>,\n    );\n  });\n\n  it('should keep track of namespace across portals (complex)', () => {\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        {usePortal(\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n          </svg>,\n        )}\n        <p {...expectHTML} />\n        <svg {...expectSVG}>\n          <image {...expectSVG} />\n        </svg>\n        <svg {...expectSVG}>\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n          </svg>\n          <image {...expectSVG} />\n        </svg>\n        <p {...expectHTML} />\n      </div>,\n    );\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        <svg {...expectSVG}>\n          <svg {...expectSVG}>\n            <image {...expectSVG} />\n            {usePortal(\n              <svg {...expectSVG}>\n                <image {...expectSVG} />\n                <svg {...expectSVG}>\n                  <image {...expectSVG} />\n                </svg>\n                <image {...expectSVG} />\n              </svg>,\n            )}\n            <image {...expectSVG} />\n            <foreignObject {...expectSVG}>\n              <p {...expectHTML} />\n              {usePortal(<p {...expectHTML} />)}\n              <p {...expectHTML} />\n            </foreignObject>\n          </svg>\n          <image {...expectSVG} />\n        </svg>\n        <p {...expectHTML} />\n      </div>,\n    );\n    assertNamespacesMatch(\n      <div {...expectHTML}>\n        <svg {...expectSVG}>\n          <foreignObject {...expectSVG}>\n            <p {...expectHTML} />\n            {usePortal(\n              <svg {...expectSVG}>\n                <image {...expectSVG} />\n                <svg {...expectSVG}>\n                  <image {...expectSVG} />\n                  <foreignObject {...expectSVG}>\n                    <p {...expectHTML} />\n                  </foreignObject>\n                  {usePortal(<p {...expectHTML} />)}\n                </svg>\n                <image {...expectSVG} />\n              </svg>,\n            )}\n            <p {...expectHTML} />\n          </foreignObject>\n          <image {...expectSVG} />\n        </svg>\n        <p {...expectHTML} />\n      </div>,\n    );\n  });\n\n  it('should unwind namespaces on uncaught errors', () => {\n    function BrokenRender() {\n      throw new Error('Hello');\n    }\n\n    expect(() => {\n      assertNamespacesMatch(\n        <svg {...expectSVG}>\n          <BrokenRender />\n        </svg>,\n      );\n    }).toThrow(); // Hello\n\n    assertNamespacesMatch(<div {...expectHTML} />);\n  });\n\n  it('should pass portal context when rendering subtree elsewhere', () => {\n    const portalContainer = document.createElement('div');\n\n    class Comp extends Component {\n      public render() {\n        return <div>{this.context.foo}</div>;\n      }\n    }\n\n    class Parent extends Component {\n      public getChildContext() {\n        return {\n          foo: 'bar',\n        };\n      }\n\n      public render() {\n        return createPortal(<Comp />, portalContainer);\n      }\n    }\n\n    render(<Parent />, container);\n    expect(container.innerHTML).toBe('');\n    expect(portalContainer.innerHTML).toBe('<div>bar</div>');\n  });\n\n  it('should update portal context if it changes due to setState', () => {\n    const portalContainer = document.createElement('div');\n\n    class Comp extends Component {\n      public render() {\n        return <div>{this.context.foo + '-' + this.context.getFoo()}</div>;\n      }\n    }\n\n    class Parent extends Component {\n      public state = {\n        bar: 'initial',\n      };\n\n      public getChildContext() {\n        return {\n          foo: this.state.bar,\n          getFoo: () => this.state.bar,\n        };\n      }\n\n      public render() {\n        return createPortal(<Comp />, portalContainer);\n      }\n    }\n    const instance = render(<Parent />, container);\n    expect(portalContainer.innerHTML).toBe('<div>initial-initial</div>');\n    expect(container.innerHTML).toBe('');\n\n    instance.setState({ bar: 'changed' });\n\n    expect(portalContainer.innerHTML).toBe('<div>changed-changed</div>');\n    expect(container.innerHTML).toBe('');\n\n    render(null, container);\n\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should update portal context if it changes due to re-render', () => {\n    const portalContainer = document.createElement('div');\n\n    class Comp extends Component {\n      public render() {\n        return <div>{this.context.foo + '-' + this.context.getFoo()}</div>;\n      }\n    }\n\n    interface ParentProps {\n      bar: string;\n    }\n\n    class Parent extends Component<ParentProps> {\n      public getChildContext() {\n        return {\n          foo: this.props.bar,\n          getFoo: () => this.props.bar,\n        };\n      }\n\n      public render() {\n        return createPortal(<Comp />, portalContainer);\n      }\n    }\n\n    render(<Parent bar=\"initial\" />, container);\n    expect(portalContainer.innerHTML).toBe('<div>initial-initial</div>');\n    expect(container.innerHTML).toBe('');\n\n    render(<Parent bar=\"changed\" />, container);\n    expect(portalContainer.innerHTML).toBe('<div>changed-changed</div>');\n    expect(container.innerHTML).toBe('');\n\n    render(null, container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should update portal context if it changes due to re-render - functional comps', () => {\n    const portalContainer = document.createElement('div');\n\n    function Comp(_, { foo, getFoo }) {\n      return <div>{foo + '-' + getFoo()}</div>;\n    }\n\n    interface ParentProps {\n      bar: string;\n    }\n\n    class Parent extends Component<ParentProps> {\n      public getChildContext() {\n        return {\n          foo: this.props.bar,\n          getFoo: () => this.props.bar,\n        };\n      }\n\n      public render() {\n        return createPortal(<Comp />, portalContainer);\n      }\n    }\n\n    render(<Parent bar=\"initial\" />, container);\n    expect(portalContainer.innerHTML).toBe('<div>initial-initial</div>');\n    expect(container.innerHTML).toBe('');\n\n    render(<Parent bar=\"changed\" />, container);\n    expect(portalContainer.innerHTML).toBe('<div>changed-changed</div>');\n    expect(container.innerHTML).toBe('');\n\n    render(null, container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should update portal context if it changes due to re-render - functional comps #2', () => {\n    const portalContainer = document.createElement('div');\n\n    function Comp({ foo }) {\n      return <div>{foo}</div>;\n    }\n\n    function Parent({ bar }) {\n      return createPortal(<Comp foo={bar} />, portalContainer);\n    }\n\n    render(<Parent bar=\"initial\" />, container);\n    expect(portalContainer.innerHTML).toBe('<div>initial</div>');\n    expect(container.innerHTML).toBe('');\n\n    render(<Parent bar=\"changed\" />, container);\n    expect(portalContainer.innerHTML).toBe('<div>changed</div>');\n    expect(container.innerHTML).toBe('');\n\n    render(null, container);\n    expect(portalContainer.innerHTML).toBe('');\n    expect(container.innerHTML).toBe('');\n  });\n\n  describe('Changing portal to other type of vNode', () => {\n    it('Should remove portal from its container when its replaced by div', () => {\n      const portalContainer = document.createElement('div');\n\n      function Comp({ foo }) {\n        return <div>{foo}</div>;\n      }\n\n      function Parent({ bar, port }) {\n        let innerContent;\n\n        if (port) {\n          innerContent = createPortal(<Comp foo={bar} />, portalContainer);\n        } else {\n          innerContent = <div>{bar}</div>;\n        }\n\n        return <div>{innerContent}</div>;\n      }\n\n      render(<Parent port={false} bar=\"initial\" />, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe('<div><div>initial</div></div>');\n\n      render(<Parent port={true} bar=\"changed\" />, container);\n      expect(portalContainer.innerHTML).toBe('<div>changed</div>');\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(<Parent port={false} bar=\"triple\" />, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe('<div><div>triple</div></div>');\n\n      render(null, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should remove portal from its container when its replaced by class component', () => {\n      const portalContainer = document.createElement('div');\n      interface CompProps {\n        children: InfernoNode;\n      }\n\n      class Comp extends Component<CompProps> {\n        public render({ children }: CompProps) {\n          return <div>{children}</div>;\n        }\n      }\n\n      function Parent({ bar, port }) {\n        let innerContent;\n\n        if (port) {\n          innerContent = createPortal(<Comp children={bar} />, portalContainer);\n        } else {\n          innerContent = (\n            <Comp>\n              <span>{bar}</span>\n            </Comp>\n          );\n        }\n\n        return <div>{innerContent}</div>;\n      }\n\n      render(<Parent port={false} bar=\"initial\" />, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe(\n        '<div><div><span>initial</span></div></div>',\n      );\n\n      render(<Parent port={true} bar=\"changed\" />, container);\n      expect(portalContainer.innerHTML).toBe('<div>changed</div>');\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(<Parent port={false} bar=\"triple\" />, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe(\n        '<div><div><span>triple</span></div></div>',\n      );\n\n      render(null, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should remove portal from its container when its replaced by functional component', () => {\n      const portalContainer = document.createElement('div');\n\n      function Comp({ children }) {\n        return <div>{children}</div>;\n      }\n\n      function Parent({ bar, port }) {\n        let innerContent;\n\n        if (port) {\n          innerContent = createPortal(<Comp children={bar} />, portalContainer);\n        } else {\n          innerContent = (\n            <Comp>\n              <span>{bar}</span>\n            </Comp>\n          );\n        }\n\n        return <div>{innerContent}</div>;\n      }\n\n      render(<Parent port={false} bar=\"initial\" />, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe(\n        '<div><div><span>initial</span></div></div>',\n      );\n\n      render(<Parent port={true} bar=\"changed\" />, container);\n      expect(portalContainer.innerHTML).toBe('<div>changed</div>');\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(<Parent port={false} bar=\"triple\" />, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe(\n        '<div><div><span>triple</span></div></div>',\n      );\n\n      render(null, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should remove portal from its container when its replaced by invalid node', () => {\n      const portalContainer = document.createElement('div');\n\n      function Comp({ children }) {\n        return <div>{children}</div>;\n      }\n\n      function Parent({ bar, port }) {\n        let innerContent;\n\n        if (port) {\n          innerContent = createPortal(<Comp children={bar} />, portalContainer);\n        } else {\n          innerContent = false;\n        }\n\n        return <div>{innerContent}</div>;\n      }\n\n      render(<Parent port={false} bar=\"initial\" />, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(<Parent port={true} bar=\"changed\" />, container);\n      expect(portalContainer.innerHTML).toBe('<div>changed</div>');\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(<Parent port={false} bar=\"triple\" />, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(null, container);\n      expect(portalContainer.innerHTML).toBe('');\n      expect(container.innerHTML).toBe('');\n    });\n\n    describe('Multiple portals', () => {\n      it('#1', () => {\n        const portalContainer = document.createElement('div');\n\n        let mountCount = 0;\n        let unMountCount = 0;\n\n        interface CompProps {\n          children: InfernoNode;\n        }\n\n        class Comp extends Component<CompProps> {\n          public componentWillMount() {\n            mountCount++;\n          }\n\n          public componentWillUnmount() {\n            unMountCount++;\n          }\n\n          public render({ children }) {\n            return <div>{children}</div>;\n          }\n        }\n\n        function Parent({ port }) {\n          let innerContent;\n\n          if (port) {\n            innerContent = [\n              createPortal(<Comp key={1} children={1} />, portalContainer),\n              createPortal(<Comp key={2} children={2} />, portalContainer),\n              createPortal(<Comp key={3} children={3} />, portalContainer),\n            ];\n          } else {\n            innerContent = false;\n          }\n\n          return <div>{innerContent}</div>;\n        }\n\n        render(<Parent port={false} />, container);\n        expect(portalContainer.innerHTML).toBe('');\n        expect(container.innerHTML).toBe('<div></div>');\n        expect(mountCount).toBe(0);\n        expect(unMountCount).toBe(0);\n\n        render(<Parent port={true} />, container);\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>2</div><div>3</div>',\n        );\n        expect(container.innerHTML).toBe('<div></div>');\n        expect(mountCount).toBe(3);\n        expect(unMountCount).toBe(0);\n\n        render(<Parent port={false} />, container);\n        expect(portalContainer.innerHTML).toBe('');\n        expect(container.innerHTML).toBe('<div></div>');\n        expect(mountCount).toBe(3);\n        expect(unMountCount).toBe(3);\n\n        render(null, container);\n        expect(portalContainer.innerHTML).toBe('');\n        expect(container.innerHTML).toBe('');\n        expect(mountCount).toBe(3);\n        expect(unMountCount).toBe(3);\n      });\n\n      it('#2', () => {\n        const portalContainer = document.createElement('div');\n\n        let mountCount = 0;\n        let unMountCount = 0;\n\n        interface CompProps {\n          children: InfernoNode;\n        }\n\n        class Comp extends Component<CompProps> {\n          public componentWillMount() {\n            mountCount++;\n          }\n\n          public componentWillUnmount() {\n            unMountCount++;\n          }\n\n          public render({ children }) {\n            return <div>{children}</div>;\n          }\n        }\n\n        function Parent({\n          port,\n          nothing,\n        }: {\n          port?: boolean;\n          nothing?: boolean;\n        }) {\n          let innerContent;\n\n          if (!nothing) {\n            if (port) {\n              innerContent = [\n                createPortal(<Comp key={1} children={1} />, portalContainer),\n                createPortal(<Comp key={2} children={2} />, portalContainer),\n                createPortal(<Comp key={3} children={3} />, portalContainer),\n              ];\n            } else {\n              innerContent = [\n                createPortal(<Comp key={1} children={1} />, portalContainer),\n                createPortal(<Comp key={3} children={3} />, portalContainer),\n                createPortal(<Comp key={5} children={5} />, portalContainer),\n              ];\n            }\n          }\n\n          return <div>{innerContent}</div>;\n        }\n\n        render(<Parent nothing={true} port={false} />, container);\n        expect(portalContainer.innerHTML).toBe('');\n        expect(container.innerHTML).toBe('<div></div>');\n        expect(mountCount).toBe(0);\n        expect(unMountCount).toBe(0);\n\n        render(<Parent port={true} />, container);\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>2</div><div>3</div>',\n        );\n        expect(container.innerHTML).toBe('<div></div>');\n        expect(mountCount).toBe(3);\n        expect(unMountCount).toBe(0);\n\n        render(<Parent port={false} />, container);\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>3</div><div>5</div>',\n        );\n        expect(container.innerHTML).toBe('<div></div>');\n        expect(mountCount).toBe(4); // 5 is new\n        expect(unMountCount).toBe(1); // 2 is dead\n\n        render(null, container);\n        expect(portalContainer.innerHTML).toBe('');\n        expect(container.innerHTML).toBe('');\n        expect(mountCount).toBe(4);\n        expect(unMountCount).toBe(4);\n      });\n\n      it('Should be possible to move nodes around portals #1', () => {\n        const portalContainer = document.createElement('div');\n\n        let mountCount = 0;\n        let unMountCount = 0;\n\n        interface CompProps {\n          children: InfernoNode;\n        }\n\n        class Comp extends Component<CompProps> {\n          public componentWillMount() {\n            mountCount++;\n          }\n\n          public componentWillUnmount() {\n            unMountCount++;\n          }\n\n          public render({ children }) {\n            return <div>{children}</div>;\n          }\n        }\n\n        function Parent({ port }: { port?: boolean }) {\n          let innerContent;\n\n          if (port) {\n            innerContent = [\n              <span key=\"a\">a</span>,\n              createPortal(<Comp key={1} children={1} />, portalContainer),\n              <span key=\"b\">b</span>,\n              createPortal(<Comp key={2} children={2} />, portalContainer),\n              <span key=\"c\">c</span>,\n              createPortal(<Comp key={3} children={3} />, portalContainer),\n            ];\n          } else {\n            innerContent = [\n              createPortal(<Comp key={1} children={1} />, portalContainer),\n              <span key=\"c\">c</span>,\n              createPortal(<Comp key={3} children={3} />, portalContainer),\n              createPortal(<Comp key={5} children={5} />, portalContainer),\n              <span key=\"a\">a</span>,\n              <span key=\"b\">b</span>,\n            ];\n          }\n\n          return <div>{innerContent}</div>;\n        }\n\n        render(<Parent port={true} />, container);\n        expect(container.innerHTML).toBe(\n          '<div><span>a</span><span>b</span><span>c</span></div>',\n        );\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>2</div><div>3</div>',\n        );\n        expect(mountCount).toBe(3);\n        expect(unMountCount).toBe(0);\n\n        render(<Parent port={false} />, container);\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>3</div><div>5</div>',\n        );\n        expect(container.innerHTML).toBe(\n          '<div><span>c</span><span>a</span><span>b</span></div>',\n        );\n        expect(mountCount).toBe(4);\n        expect(unMountCount).toBe(1);\n\n        render(null, container);\n        expect(portalContainer.innerHTML).toBe('');\n        expect(container.innerHTML).toBe('');\n        expect(mountCount).toBe(4);\n        expect(unMountCount).toBe(4);\n      });\n\n      it('Should be possible to move nodes around portals #2', () => {\n        const portalContainer = document.createElement('div');\n\n        let mountCount = 0;\n        let unMountCount = 0;\n\n        interface CompProps {\n          children: InfernoNode;\n        }\n\n        class Comp extends Component<CompProps> {\n          public componentWillMount() {\n            mountCount++;\n          }\n\n          public componentWillUnmount() {\n            unMountCount++;\n          }\n\n          public render({ children }) {\n            return <div>{children}</div>;\n          }\n        }\n\n        function Parent({ port }: { port?: boolean }) {\n          let innerContent;\n\n          if (port) {\n            innerContent = [\n              <span key=\"a\">a</span>,\n              createPortal(<Comp key={1} children={1} />, portalContainer),\n              <span key=\"b\">b</span>,\n              createPortal(<Comp key={2} children={2} />, portalContainer),\n              <span key=\"c\">c</span>,\n              createPortal(<Comp key={3} children={3} />, portalContainer),\n            ];\n          } else {\n            innerContent = [\n              createPortal(<Comp key={1} children={1} />, portalContainer),\n              <span key=\"c\">c</span>,\n              createPortal(<Comp key={3} children={3} />, portalContainer),\n              createPortal(<Comp key={5} children={5} />, portalContainer),\n              <span key=\"a\">a</span>,\n              <span key=\"b\">b</span>,\n            ];\n          }\n\n          return <div>{innerContent}</div>;\n        }\n\n        render(<Parent port={false} />, container);\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>3</div><div>5</div>',\n        );\n        expect(container.innerHTML).toBe(\n          '<div><span>c</span><span>a</span><span>b</span></div>',\n        );\n\n        render(<Parent port={true} />, container);\n        expect(container.innerHTML).toBe(\n          '<div><span>a</span><span>b</span><span>c</span></div>',\n        );\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>3</div><div>2</div>',\n        ); // <= Portal order is based on creation\n\n        render(null, container);\n        expect(portalContainer.innerHTML).toBe('');\n        expect(container.innerHTML).toBe('');\n        expect(mountCount).toBe(4);\n        expect(unMountCount).toBe(4);\n      });\n\n      it('Should be possible to move nodes around portals when portal is root node of component #1', () => {\n        const portalContainer = document.createElement('div');\n\n        let mountCount = 0;\n        let unMountCount = 0;\n\n        interface CompProps {\n          children: InfernoNode;\n        }\n\n        class WrapPortal extends Component<CompProps> {\n          public render({ children }) {\n            return createPortal(<Comp>{children}</Comp>, portalContainer);\n          }\n        }\n\n        class Comp extends Component<CompProps> {\n          public componentWillMount() {\n            mountCount++;\n          }\n\n          public componentWillUnmount() {\n            unMountCount++;\n          }\n\n          public render({ children }) {\n            return <div>{children}</div>;\n          }\n        }\n\n        function Parent({ port }) {\n          let innerContent;\n\n          if (port) {\n            innerContent = [\n              <span key=\"a\">a</span>,\n              <WrapPortal key={1}>1</WrapPortal>,\n              <span key=\"b\">b</span>,\n              createPortal(<Comp key={2} children={2} />, portalContainer),\n              <span key=\"c\">c</span>,\n              <WrapPortal key={3}>3</WrapPortal>,\n            ];\n          } else {\n            innerContent = [\n              createPortal(<Comp key={1} children={1} />, portalContainer),\n              <span key=\"c\">c</span>,\n              createPortal(<Comp key={3} children={3} />, portalContainer),\n              createPortal(<Comp key={5} children={5} />, portalContainer),\n              <span key=\"a\">a</span>,\n              <span key=\"b\">b</span>,\n            ];\n          }\n\n          return <div>{innerContent}</div>;\n        }\n\n        render(<Parent port={false} />, container);\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>3</div><div>5</div>',\n        );\n        expect(container.innerHTML).toBe(\n          '<div><span>c</span><span>a</span><span>b</span></div>',\n        );\n\n        render(<Parent port={true} />, container);\n        expect(container.innerHTML).toBe(\n          '<div><span>a</span><span>b</span><span>c</span></div>',\n        );\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>3</div><div>2</div>',\n        ); // <= Portal order is based on creation\n\n        render(<Parent port={false} />, container);\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>3</div><div>5</div>',\n        );\n        expect(container.innerHTML).toBe(\n          '<div><span>c</span><span>a</span><span>b</span></div>',\n        );\n\n        render(null, container);\n        expect(portalContainer.innerHTML).toBe('');\n        expect(container.innerHTML).toBe('');\n        expect(mountCount).toBe(9);\n        expect(unMountCount).toBe(9);\n      });\n\n      it('Should be possible to move nodes around portals when portal is root node of component #2', () => {\n        const portalContainer = document.createElement('div');\n\n        let mountCount = 0;\n        let unMountCount = 0;\n\n        interface CompProps {\n          children: InfernoNode;\n        }\n\n        class WrapPortal extends Component<CompProps> {\n          public render({ children }) {\n            return createPortal(<Comp>{children}</Comp>, portalContainer);\n          }\n        }\n\n        class Comp extends Component<CompProps> {\n          public componentWillMount() {\n            mountCount++;\n          }\n\n          public componentWillUnmount() {\n            unMountCount++;\n          }\n\n          public render({ children }) {\n            return <div>{children}</div>;\n          }\n        }\n\n        function Parent({ port }) {\n          let innerContent;\n\n          if (port) {\n            innerContent = [\n              <span key=\"A\">A</span>,\n              <WrapPortal key={1}>1</WrapPortal>,\n              <WrapPortal key={2}>2</WrapPortal>,\n              createPortal(<Comp key={3} children={3} />, portalContainer),\n              <WrapPortal key={4}>\n                <WrapPortal>\n                  <WrapPortal>inner</WrapPortal>\n                </WrapPortal>\n              </WrapPortal>,\n              <span key=\"B\">B</span>,\n              <WrapPortal key={5}>5</WrapPortal>,\n            ];\n          } else {\n            innerContent = [\n              createPortal(<Comp key={1} children={1} />, portalContainer),\n              <span key=\"C\">C</span>,\n              <WrapPortal key={4}>\n                <span>XX</span>\n              </WrapPortal>, // <== Change nested portal into component span and move it\n              createPortal(<Comp key={3} children={3} />, portalContainer),\n              <WrapPortal key={5}>5</WrapPortal>,\n              <span key=\"A\">A</span>,\n              <span key=\"B\">B</span>,\n            ];\n          }\n\n          return <div>{innerContent}</div>;\n        }\n\n        render(<Parent port={true} />, container);\n        // 3 5 1 inner 2\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>2</div><div>3</div><div>inner</div><div></div><div></div><div>5</div>',\n        );\n        expect(container.innerHTML).toBe(\n          '<div><span>A</span><span>B</span></div>',\n        );\n        expect(mountCount).toBe(7);\n        expect(unMountCount).toBe(0);\n\n        render(<Parent port={false} />, container);\n        expect(portalContainer.innerHTML).toBe(\n          '<div>3</div><div><span>XX</span></div><div>5</div><div>1</div>',\n        );\n        expect(container.innerHTML).toBe(\n          '<div><span>C</span><span>A</span><span>B</span></div>',\n        );\n\n        render(<Parent port={true} />, container);\n        // 3 5 1 inner 2\n        expect(portalContainer.innerHTML).toBe(\n          '<div>3</div><div></div><div>5</div><div>1</div><div>inner</div><div></div><div>2</div>',\n        );\n        expect(container.innerHTML).toBe(\n          '<div><span>A</span><span>B</span></div>',\n        );\n\n        render(<Parent port={false} />, container);\n        expect(portalContainer.innerHTML).toBe(\n          '<div>3</div><div><span>XX</span></div><div>5</div><div>1</div>',\n        );\n        expect(container.innerHTML).toBe(\n          '<div><span>C</span><span>A</span><span>B</span></div>',\n        );\n\n        render(null, container);\n        expect(portalContainer.innerHTML).toBe('');\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should be possible to patch portal non keyed', () => {\n        const portalContainer = document.createElement('div');\n\n        let mountCount = 0;\n        let unMountCount = 0;\n\n        interface CompProps {\n          children: InfernoNode;\n        }\n\n        class WrapPortal extends Component<CompProps> {\n          public render({ children }) {\n            return createPortal(<Comp>{children}</Comp>, portalContainer);\n          }\n        }\n\n        class Comp extends Component<CompProps> {\n          public componentWillMount() {\n            mountCount++;\n          }\n\n          public componentWillUnmount() {\n            unMountCount++;\n          }\n\n          public render({ children }) {\n            return <div>{children}</div>;\n          }\n        }\n\n        function Parent({ port }) {\n          let innerContent;\n\n          if (port) {\n            innerContent = [\n              <span>A</span>,\n              <WrapPortal>1</WrapPortal>,\n              <WrapPortal>2</WrapPortal>,\n              createPortal(<Comp children={3} />, portalContainer),\n              <WrapPortal>\n                <WrapPortal>\n                  <WrapPortal>inner</WrapPortal>\n                </WrapPortal>\n              </WrapPortal>,\n              <span>B</span>,\n              <WrapPortal>5</WrapPortal>,\n            ];\n          } else {\n            innerContent = [\n              createPortal(<Comp children={1} />, portalContainer),\n              <span>C</span>,\n              <WrapPortal>\n                <span>XX</span>\n              </WrapPortal>, // <== Change nested portal into component span and move it\n              createPortal(<Comp children={3} />, portalContainer),\n              <WrapPortal>5</WrapPortal>,\n              <span>A</span>,\n              <span>B</span>,\n            ];\n          }\n\n          return <div>{innerContent}</div>;\n        }\n\n        render(<Parent port={true} />, container);\n        // 3 5 1 inner 2\n        expect(portalContainer.innerHTML).toBe(\n          '<div>1</div><div>2</div><div>3</div><div>inner</div><div></div><div></div><div>5</div>',\n        );\n        expect(container.innerHTML).toBe(\n          '<div><span>A</span><span>B</span></div>',\n        );\n\n        render(<Parent port={false} />, container);\n        expect(portalContainer.innerHTML).toBe(\n          '<div><span>XX</span></div><div>3</div><div>5</div><div>1</div>',\n        );\n        expect(container.innerHTML).toBe(\n          '<div><span>C</span><span>A</span><span>B</span></div>',\n        );\n\n        render(<Parent port={true} />, container);\n        // 3 5 1 inner 2\n        expect(portalContainer.innerHTML).toBe(\n          '<div>2</div><div>3</div><div></div><div>1</div><div>inner</div><div></div><div>5</div>',\n        );\n        expect(container.innerHTML).toBe(\n          '<div><span>A</span><span>B</span></div>',\n        );\n\n        render(null, container);\n        expect(portalContainer.innerHTML).toBe('');\n        expect(container.innerHTML).toBe('');\n\n        expect(mountCount).toBe(12);\n        expect(unMountCount).toBe(12);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/rendering.spec.tsx",
    "content": "import {\n  Component,\n  createTextVNode,\n  createVNode,\n  render,\n  rerender,\n} from 'inferno';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\n\ndescribe('rendering routine', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should throw error when trying to render to document.body', () => {\n    const div = createVNode(\n      VNodeFlags.HtmlElement,\n      'div',\n      null,\n      createTextVNode('1'),\n      ChildFlags.HasVNodeChildren,\n    );\n    try {\n      render(div, document.body);\n    } catch (e) {\n      expect(e.message).toEqual(\n        'Inferno Error: you cannot render() to the \"document.body\". Use an empty element as a container instead.',\n      );\n    }\n  });\n\n  it('Should throw error if second parameter is not given', () => {\n    expect(() => {\n      render(<div>1</div>, null);\n    }).toThrow();\n  });\n\n  it('Should create new object when dom exists', () => {\n    const bar = createVNode(\n      VNodeFlags.HtmlElement,\n      'div',\n      null,\n      createTextVNode('123'),\n      ChildFlags.HasVNodeChildren,\n    );\n    const foo = createVNode(\n      VNodeFlags.HtmlElement,\n      'div',\n      null,\n      bar,\n      ChildFlags.HasVNodeChildren,\n    );\n\n    render(foo, container);\n    expect(container.innerHTML).toEqual('<div><div>123</div></div>');\n\n    render(null, container);\n\n    render(foo, container);\n    expect(container.innerHTML).toEqual('<div><div>123</div></div>');\n  });\n\n  it('should be called a callback argument', () => {\n    // mounting phase\n    let called = false;\n    render(<div>Foo</div>, container, () => (called = true));\n    expect(called).toEqual(true);\n\n    // updating phase\n    called = false;\n    render(<div>Foo</div>, container, () => (called = true));\n    expect(called).toEqual(true);\n  });\n\n  it('should call a callback argument when the same element is re-rendered', () => {\n    class Foo extends Component {\n      public render() {\n        return <div>Foo</div>;\n      }\n    }\n    const element = <Foo />;\n\n    // mounting phase\n    let called = false;\n    render(element, container, () => (called = true));\n    expect(called).toEqual(true);\n\n    // updating phase\n    called = false;\n\n    render(element, container, () => (called = true));\n\n    expect(called).toEqual(true);\n  });\n\n  it('should render a component returning strings directly from render', () => {\n    const Text = ({ value }) => value;\n\n    render(<Text value=\"foo\" />, container);\n    expect(container.textContent).toEqual('foo');\n  });\n\n  it('should render a component returning numbers directly from render', () => {\n    const Text = ({ value }) => value;\n\n    render(<Text value={10} />, container);\n\n    expect(container.textContent).toEqual('10');\n  });\n\n  it('should not crash encountering low-priority tree', () => {\n    render(\n      <div hidden={true}>\n        <div />\n      </div>,\n      container,\n    );\n  });\n\n  it('should not warn when rendering into an empty container', () => {\n    const consoleSpy = spyOn(console, 'error');\n\n    render(<div>foo</div>, container);\n    expect(container.innerHTML).toBe('<div>foo</div>');\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n    expect(consoleSpy.calls.count()).toBe(0);\n\n    render(<div>bar</div>, container);\n    expect(container.innerHTML).toBe('<div>bar</div>');\n\n    expect(consoleSpy.calls.count()).toBe(0);\n  });\n\n  it('Should be possible to render Immutable datastructures', () => {\n    function Clock(props) {\n      const time = props.time + 1;\n      const array = Object.freeze([\n        <span>{'Inferno version:'}</span>,\n        <br />,\n        <span>{time}</span>,\n      ]);\n      return <div>{array}</div>;\n    }\n\n    const consoleSpy = spyOn(console, 'error');\n\n    render(<Clock time={1} />, container);\n    expect(container.innerHTML).toBe(\n      '<div><span>Inferno version:</span><br><span>2</span></div>',\n    );\n\n    render(<Clock time={2} />, container);\n    expect(container.innerHTML).toBe(\n      '<div><span>Inferno version:</span><br><span>3</span></div>',\n    );\n\n    render(<Clock time={3} />, container);\n    expect(container.innerHTML).toBe(\n      '<div><span>Inferno version:</span><br><span>4</span></div>',\n    );\n    expect(consoleSpy.calls.count()).toBe(0);\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n\n    expect(consoleSpy.calls.count()).toBe(0);\n  });\n\n  describe('createTextVNode', () => {\n    it('null/undefined textNodes should render empty text', () => {\n      render(<div>{createTextVNode(null)}</div>, container);\n\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      render(<div>{createTextVNode(undefined)}</div>, container);\n\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      render(<div>{createTextVNode('')}</div>, container);\n\n      expect(container.innerHTML).toEqual('<div></div>');\n    });\n\n    it('Should render 0 as \"0\"', () => {\n      render(<div>{createTextVNode(0)}</div>, container);\n\n      expect(container.innerHTML).toEqual('<div>0</div>');\n\n      render(<div>{createTextVNode('0')}</div>, container);\n\n      expect(container.innerHTML).toEqual('<div>0</div>');\n\n      render(<div>{createTextVNode('')}</div>, container);\n\n      expect(container.innerHTML).toEqual('<div></div>');\n    });\n  });\n\n  describe('className', () => {\n    it('Should override destructured property when defined', function () {\n      const testObj = {\n        className: 'test',\n      };\n\n      render(<div {...testObj} className=\"bar\" />, container);\n\n      expect(container.innerHTML).toEqual('<div class=\"bar\"></div>');\n    });\n  });\n\n  describe('Swapping children', () => {\n    it('Swapping children in component should affect hoisted children', () => {\n      interface HelloProps {\n        name: string;\n      }\n\n      class Hello extends Component<HelloProps> {\n        public render(props) {\n          const child = props.children;\n\n          child.reverse();\n\n          return <div>Hello {child}</div>;\n        }\n      }\n\n      const data = [1, 2];\n\n      render(\n        <div>\n          <Hello name=\"World\">{data}</Hello>\n          <Hello name=\"World\">{data}</Hello>\n          <Hello name=\"World\">{data}</Hello>\n        </div>,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div>Hello 21</div><div>Hello 12</div><div>Hello 21</div></div>',\n      );\n\n      render(\n        <div>\n          <Hello name=\"World\">{data}</Hello>\n          <Hello name=\"World\">{data}</Hello>\n          <Hello name=\"World\">{data}</Hello>\n        </div>,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual(\n        '<div><div>Hello 12</div><div>Hello 21</div><div>Hello 12</div></div>',\n      );\n    });\n  });\n\n  // https://jsfiddle.net/Ldqyu475/\n  describe('render during component construction', () => {\n    it('Should queue updates and not fail if HOC updates during child component construction', () => {\n      interface HelloProps {\n        name?: string;\n        tag: number;\n        callback: () => void;\n      }\n      interface HelloState {\n        foo: string;\n      }\n\n      class Hello extends Component<HelloProps, HelloState> {\n        public state: HelloState;\n        constructor(props, context) {\n          super(props, context);\n\n          this.state = { foo: 'foobar' };\n\n          // expect(container.innerHTML).toBe('');\n          expect(this.props.tag).toBe(0);\n          props.callback();\n          // expect(container.innerHTML).toBe('');\n          expect(this.props.tag).toBe(0);\n          props.callback();\n          // expect(container.innerHTML).toBe('');\n          expect(this.props.tag).toBe(0);\n          props.callback();\n          // expect(container.innerHTML).toBe('');\n          expect(this.props.tag).toBe(0);\n        }\n\n        public render() {\n          return (\n            <div>\n              Hello {this.props.name} {this.props.tag} {this.state.foo}\n            </div>\n          );\n        }\n      }\n\n      interface HOCProps {\n        name?: string;\n        renderAgain: () => void;\n      }\n\n      interface HOCState {\n        tag: number;\n      }\n\n      class HOC extends Component<HOCProps, HOCState> {\n        public state: HOCState;\n\n        constructor(props, context) {\n          super(props, context);\n\n          this.state = { tag: 0 };\n\n          this.renderAgain = this.renderAgain.bind(this);\n        }\n\n        public renderAgain() {\n          this.props.renderAgain();\n        }\n\n        public render() {\n          return (\n            <div>\n              {this.state.tag > 0 ? <div>1</div> : null}\n              {this.state.tag > 1 ? <div>1</div> : null}\n              <Hello\n                name={this.props.name}\n                tag={this.state.tag}\n                callback={this.renderAgain}\n              />\n              <span>2</span>\n            </div>\n          );\n        }\n      }\n\n      interface ParentState {\n        foo: boolean;\n      }\n\n      class Parent extends Component<unknown, ParentState> {\n        public state: ParentState;\n        constructor(props, context) {\n          super(props, context);\n\n          this.state = {\n            foo: false,\n          };\n        }\n\n        public render() {\n          return (\n            <span\n              id=\"click\"\n              onClick={() => {\n                this.setState({ foo: !this.state.foo });\n              }}\n            >\n              {this.state.foo ? (\n                <HOC\n                  renderAgain={() => {\n                    this.setState({});\n                  }}\n                />\n              ) : null}\n            </span>\n          );\n        }\n      }\n\n      render(<Parent />, container);\n\n      expect(container.innerHTML).toBe('<span id=\"click\"></span>');\n\n      container.querySelector('#click').click();\n      rerender();\n\n      expect(container.innerHTML).toBe(\n        '<span id=\"click\"><div><div>Hello  0 foobar</div><span>2</span></div></span>',\n      );\n\n      container.querySelector('#click').click();\n      rerender();\n\n      expect(container.innerHTML).toBe('<span id=\"click\"></span>');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/select.spec.tsx",
    "content": "import { render } from 'inferno';\nimport { triggerEvent } from 'inferno-utils';\n\ndescribe('Select selectedIndex', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should render select with selectedIndex -1', () => {\n    render(\n      <select selectedIndex={-1}>\n        <option value=\"0\">Leonardo</option>\n        <option value=\"1\">Donatello</option>\n        <option value=\"2\">Rafael</option>\n        <option value=\"3\">Michelangelo</option>\n        <option value=\"4\">Splinter</option>\n      </select>,\n      container,\n    );\n\n    const select = container.firstElementChild;\n    if (window.name === 'nodejs') {\n      // bug in JSdom =(\n      expect(select.selectedIndex).toBe(0);\n    } else {\n      expect(select.selectedIndex).toBe(-1);\n    }\n  });\n\n  it('Should render select with selected option \"3\"', () => {\n    render(\n      <select selectedIndex={3}>\n        <option value=\"0\">Leonardo</option>\n        <option value=\"1\">Donatello</option>\n        <option value=\"2\">Rafael</option>\n        <option value=\"3\">Michelangelo</option>\n        <option value=\"4\">Splinter</option>\n      </select>,\n      container,\n    );\n\n    const select = container.firstElementChild;\n    expect(select.selectedIndex).toBe(3);\n    expect(select.value).toBe('3');\n  });\n\n  it('Should render select without changes if value is not set', () => {\n    render(\n      <select selectedIndex={3}>\n        <option value=\"0\">Leonardo</option>\n        <option value=\"1\">Donatello</option>\n        <option value=\"2\">Rafael</option>\n        <option value=\"3\">Michelangelo</option>\n        <option value=\"4\">Splinter</option>\n      </select>,\n      container,\n    );\n\n    const select = container.firstElementChild;\n    select.value = '0';\n    triggerEvent('change', select);\n    expect(select.selectedIndex).toBe(0);\n    expect(select.value).toBe('0');\n  });\n\n  it('Should strict render select if value set', () => {\n    render(\n      <select selectedIndex={3} value={'3'}>\n        <option value=\"0\">Leonardo</option>\n        <option value=\"1\">Donatello</option>\n        <option value=\"2\">Rafael</option>\n        <option value=\"3\">Michelangelo</option>\n        <option value=\"4\">Splinter</option>\n      </select>,\n      container,\n    );\n\n    const select = container.firstElementChild;\n    select.value = '0';\n    triggerEvent('change', select);\n    expect(select.selectedIndex).toBe(3);\n    expect(select.value).toBe('3');\n  });\n\n  it('Should not render attribute selectedIndex', () => {\n    render(\n      <select selectedIndex={-1}>\n        <option value=\"0\">Leonardo</option>\n        <option value=\"1\">Donatello</option>\n        <option value=\"2\">Rafael</option>\n        <option value=\"3\">Michelangelo</option>\n        <option value=\"4\">Splinter</option>\n      </select>,\n      container,\n    );\n\n    const select = container.firstElementChild;\n    expect(select.getAttribute('selectedIndex')).toBe(null);\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/select2.spec.tsx",
    "content": "import { Component, type InfernoNode, render, Fragment } from 'inferno';\n\ndescribe('Select / select multiple (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should render \"select\" boolean on select options with numbers', () => {\n    render(\n      <select multiple={true} value={null}>\n        <option value={1}>1</option>\n        <option value={2}>2</option>\n      </select>,\n      container,\n    );\n    render(\n      <select multiple={true} value={undefined}>\n        <option value={1}>1</option>\n        <option value={2}>1</option>\n      </select>,\n      container,\n    );\n    render(\n      <select multiple={true} value={2}>\n        <option value={1}>1</option>\n        <option value={2}>2</option>\n      </select>,\n      container,\n    );\n\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"1\">1</option><option value=\"2\">2</option></select>',\n    );\n\n    render(\n      <select multiple={true} value={1}>\n        <option value={1}>1</option>\n        <option value={2}>2</option>\n      </select>,\n      container,\n    );\n\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"1\">1</option><option value=\"2\">2</option></select>',\n    );\n\n    render(\n      <select multiple={true} value={'foo'}>\n        <option value={1}>1</option>\n        <option value={2}>2</option>\n      </select>,\n      container,\n    );\n\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"1\">1</option><option value=\"2\">2</option></select>',\n    );\n  });\n\n  it('should render \"select\" boolean on select options #2', () => {\n    render(\n      // @ts-expect-error\n      <select multiple={true} value={false}>\n        <option value=\"foo\">foo</option>\n        <option value=\"bar\">bar</option>\n      </select>,\n      container,\n    );\n    render(\n      <select multiple={true} value={'foo'}>\n        <option value=\"foo\">foo</option>\n        <option value=\"bar\">bar</option>\n      </select>,\n      container,\n    );\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>',\n    );\n    render(\n      // @ts-expect-error\n      <select multiple={true} value={false}>\n        <option value=\"foo\">foo</option>\n        <option value=\"bar\">bar</option>\n      </select>,\n      container,\n    );\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>',\n    );\n\n    render(\n      <select multiple={true} value={'bar'}>\n        <option value=\"foo\">foo</option>\n        <option value=\"bar\">bar</option>\n      </select>,\n      container,\n    );\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>',\n    );\n  });\n\n  it('should populate the value attribute on select multiple using groups', () => {\n    const template = (val) => (\n      <select multiple={true} value={val}>\n        <optgroup label=\"foo-group\">\n          <option value=\"foo\" />\n        </optgroup>\n        <optgroup label=\"bar-group\" disabled>\n          <option value=\"bar\" />\n        </optgroup>\n      </select>\n    );\n\n    // render(template(undefined), container);\n    render(template(['foo', 'bar']), container);\n\n    expect(container.firstChild.children[0].disabled).toEqual(false);\n    expect(container.firstChild.children[1].disabled).toEqual(true);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].children[0].selected).toEqual(true);\n\n    render(template([]), container);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(\n      false,\n    );\n    expect(container.firstChild.children[1].children[0].selected).toEqual(\n      false,\n    );\n\n    render(template('foo'), container);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].children[0].selected).toEqual(\n      false,\n    );\n\n    render(template('bar'), container);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(\n      false,\n    );\n    expect(container.firstChild.children[1].children[0].selected).toEqual(true);\n\n    render(template(false), container);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(\n      false,\n    );\n    expect(container.firstChild.children[1].children[0].selected).toEqual(\n      false,\n    );\n  });\n\n  it('should not fail if optgroup is empty', () => {\n    const template = (val) => (\n      <select multiple={true} value={val}>\n        <optgroup label=\"foo-group\">\n          <option value=\"foo\" />\n        </optgroup>\n        <optgroup />\n        <optgroup label=\"bar-group\" disabled>\n          <option value=\"bar\" />\n        </optgroup>\n      </select>\n    );\n\n    // render(template(undefined), container);\n    render(template(['foo', 'bar']), container);\n  });\n\n  it('Should be possible to render empty select', () => {\n    render(<select value=\"test\" />, container);\n\n    expect(container.innerHTML).toEqual('<select></select>');\n  });\n\n  it('should populate the value attribute on select multiple using groups, multiple optgroups and options', () => {\n    const template = (val) => (\n      <select multiple={true} value={val}>\n        <optgroup label=\"foo-group\">\n          <option value=\"foo\" />\n          <option value=\"foo2\" />\n          <option value=\"foo3\" />\n        </optgroup>\n        <optgroup label=\"bar-group\" disabled>\n          <option value=\"bar\" />\n          <option value=\"bar2\" />\n          <option value=\"bar3\" />\n        </optgroup>\n      </select>\n    );\n\n    // render(template(undefined), container);\n    render(template(['foo', 'bar2']), container);\n\n    expect(container.firstChild.children[0].disabled).toEqual(false);\n    expect(container.firstChild.children[1].disabled).toEqual(true);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option><option value=\"foo2\"></option><option value=\"foo3\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option><option value=\"bar2\"></option><option value=\"bar3\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].children[1].selected).toEqual(true);\n\n    render(template([]), container);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option><option value=\"foo2\"></option><option value=\"foo3\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option><option value=\"bar2\"></option><option value=\"bar3\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(\n      false,\n    );\n    expect(container.firstChild.children[1].children[0].selected).toEqual(\n      false,\n    );\n\n    render(template('foo'), container);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option><option value=\"foo2\"></option><option value=\"foo3\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option><option value=\"bar2\"></option><option value=\"bar3\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].children[0].selected).toEqual(\n      false,\n    );\n\n    render(template('bar'), container);\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(\n      false,\n    );\n    expect(container.firstChild.children[1].children[0].selected).toEqual(true);\n\n    render(template(false), container);\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(\n      false,\n    );\n    expect(container.firstChild.children[1].children[0].selected).toEqual(\n      false,\n    );\n  });\n\n  it('should render \"select\" boolean on select options #3', () => {\n    render(\n      <select multiple={true} value={'foo'}>\n        <option value=\"foo\">foo</option>\n        <option value=\"bar\">bar</option>\n      </select>,\n      container,\n    );\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      // Missing selected markup\n      '<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>',\n    );\n  });\n\n  it('should render \"select\" boolean on select options #1', () => {\n    render(\n      <select multiple={true} value={'foo'}>\n        <option value=\"foo\">foo</option>\n        <option value=\"bar\">bar</option>\n      </select>,\n      container,\n    );\n\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>',\n    );\n\n    render(\n      // @ts-expect-error\n      <select multiple={true} value={false}>\n        <option value=\"foo\">foo</option>\n        <option value=\"bar\">bar</option>\n      </select>,\n      container,\n    );\n\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>',\n    );\n  });\n\n  it('should assure the value attribute also set the value property for `textarea`', () => {\n    render(<textarea value={'foo'} />, container);\n    expect(container.firstChild.value).toEqual('foo');\n    render(<textarea value={'bar'} />, container);\n    expect(container.firstChild.value).toEqual('bar');\n    render(<textarea value={'bar'} />, container);\n    expect(container.firstChild.value).toEqual('bar');\n    render(<textarea value={'foo'} />, container);\n    expect(container.firstChild.value).toEqual('foo');\n    render(<textarea value={null} />, container);\n    expect(container.firstChild.value).toEqual('');\n    render(<textarea value={undefined} />, container);\n    expect(container.firstChild.value).toEqual('');\n    render(<textarea value={'bar'} />, container);\n    expect(container.firstChild.value).toEqual('bar');\n    render(<textarea value={[]} />, container);\n    expect(container.firstChild.value).toEqual('');\n\n    // @ts-expect-error\n    render(<textarea value={{}} />, container);\n    expect(container.firstChild.value).toEqual('[object Object]');\n  });\n\n  it('should handle when multiple values passed in as an array', () => {\n    render(\n      <select multiple={true} value={['a', 'b', 'c']}>\n        <option value={'a'}>a</option>\n        <option value={'b'}>b</option>\n        <option value={'c'}>c</option>\n        <option value={'d'}>d</option>\n      </select>,\n      container,\n    );\n\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.firstChild.children[2].selected).toEqual(true);\n    expect(container.firstChild.children[3].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"a\">a</option><option value=\"b\">b</option><option value=\"c\">c</option><option value=\"d\">d</option></select>',\n    );\n  });\n\n  it('should handle when multiple options with selected set', () => {\n    render(\n      <select multiple={true}>\n        <option value=\"a\" selected={true}>\n          a\n        </option>\n        <option value=\"b\" selected={true}>\n          b\n        </option>\n        <option value=\"c\" selected={true}>\n          c\n        </option>\n        <option value=\"d\">d</option>\n      </select>,\n      container,\n    );\n\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.firstChild.children[2].selected).toEqual(true);\n    expect(container.firstChild.children[3].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"a\">a</option><option value=\"b\">b</option><option value=\"c\">c</option><option value=\"d\">d</option></select>',\n    );\n  });\n\n  it('Should render empty select', () => {\n    render(<select />, container);\n    expect(container.innerHTML).toEqual('<select></select>');\n  });\n\n  it('should render defaultValue', () => {\n    render(\n      <select defaultValue=\"b\">\n        <option value=\"a\">a</option>\n        <option value=\"b\">b</option>\n        <option value=\"c\">c</option>\n        <option value=\"d\">d</option>\n      </select>,\n      container,\n    );\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.firstChild.children[2].selected).toEqual(false);\n    expect(container.firstChild.children[3].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select><option value=\"a\">a</option><option value=\"b\">b</option><option value=\"c\">c</option><option value=\"d\">d</option></select>',\n    );\n  });\n\n  it('should render multiple defaultValue', () => {\n    render(\n      <select multiple={true} defaultValue={['a', 'b', 'c']}>\n        <option value={'a'}>a</option>\n        <option value={'b'}>b</option>\n        <option value={'c'}>c</option>\n        <option value={'d'}>d</option>\n      </select>,\n      container,\n    );\n\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.firstChild.children[2].selected).toEqual(true);\n    expect(container.firstChild.children[3].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"a\">a</option><option value=\"b\">b</option><option value=\"c\">c</option><option value=\"d\">d</option></select>',\n    );\n  });\n\n  it('should not touch selections, if value or selected, is null or undefined', () => {\n    render(\n      <select>\n        <option value=\"a\">a</option>\n        <option value=\"b\">b</option>\n      </select>,\n      container,\n    );\n    container.firstChild.children[1].selected = true;\n    render(\n      <select>\n        <option value=\"a\">a</option>\n        <option value=\"b\">b</option>\n      </select>,\n      container,\n    );\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n  });\n\n  it('should render specified default selected option', () => {\n    render(\n      <select>\n        <option value=\"a\">a</option>\n        <option selected={true} value=\"b\">\n          b\n        </option>\n      </select>,\n      container,\n    );\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(true); // Currently failing due to issue #1031\n  });\n\n  it('Should have selectedIndex -1 and value as null when value is removed - Github #1105', () => {\n    render(\n      <select id=\"sel\" value=\"\">\n        <option value=\"\">a</option>\n      </select>,\n      container,\n    );\n    expect(container.firstChild.selectedIndex).toBe(0);\n    expect(container.firstChild.value).toBe('');\n\n    render(\n      <select id=\"sel\">\n        <option value=\"\">a</option>\n      </select>,\n      container,\n    );\n    expect(container.firstChild.value).toBe('');\n    expect([0, -1]).toContain(container.firstChild.selectedIndex);\n  });\n\n  it('Should be possible to render select element with options wrapped in functional Component', () => {\n    interface CustomOptionProps {\n      selected?: boolean;\n      value: number;\n      children: InfernoNode;\n    }\n    const CustomOption = ({ selected, value, children }: CustomOptionProps) => (\n      <option selected={selected} value={value}>\n        {children}\n      </option>\n    );\n\n    render(\n      <select value={1}>\n        <CustomOption value={1}>1st</CustomOption>\n        <CustomOption value={2}>2nd</CustomOption>\n        <CustomOption value={3}>3rd</CustomOption>\n      </select>,\n      container,\n    );\n\n    const selectElement = container.firstChild;\n\n    expect(container.innerHTML).toEqual(\n      '<select><option value=\"1\">1st</option><option value=\"2\">2nd</option><option value=\"3\">3rd</option></select>',\n    );\n    expect(selectElement.children[0].selected).toBe(true);\n    expect(selectElement.children[1].selected).toBe(false);\n    expect(selectElement.children[2].selected).toBe(false);\n\n    render(\n      <select value={2}>\n        <CustomOption key={1} value={1}>\n          1st\n        </CustomOption>\n        <CustomOption key={2} value={2}>\n          2nd\n        </CustomOption>\n        <CustomOption key={3} value={3}>\n          3rd\n        </CustomOption>\n      </select>,\n      container,\n    );\n\n    expect(container.innerHTML).toEqual(\n      '<select><option value=\"1\">1st</option><option value=\"2\">2nd</option><option value=\"3\">3rd</option></select>',\n    );\n    expect(selectElement.children[0].selected).toBe(false);\n    expect(selectElement.children[1].selected).toBe(true);\n    expect(selectElement.children[2].selected).toBe(false);\n  });\n\n  it('Should be possible to render select element with options wrapped in Class Component', () => {\n    interface CustomOptionProps {\n      selected?: boolean;\n      value: number;\n      children: InfernoNode;\n    }\n\n    class CustomOption extends Component<CustomOptionProps> {\n      public render() {\n        return <option value={this.props.value}>{this.props.children}</option>;\n      }\n    }\n\n    render(\n      <select value={1}>\n        <CustomOption value={1}>1st</CustomOption>\n        <CustomOption value={2}>2nd</CustomOption>\n        <CustomOption value={3}>3rd</CustomOption>\n      </select>,\n      container,\n    );\n\n    const selectElement = container.firstChild;\n\n    expect(container.innerHTML).toEqual(\n      '<select><option value=\"1\">1st</option><option value=\"2\">2nd</option><option value=\"3\">3rd</option></select>',\n    );\n    expect(selectElement.children[0].selected).toBe(true);\n    expect(selectElement.children[1].selected).toBe(false);\n    expect(selectElement.children[2].selected).toBe(false);\n\n    render(\n      <select value={2}>\n        <CustomOption key={1} value={1}>\n          1st\n        </CustomOption>\n        <CustomOption key={2} value={2}>\n          2nd\n        </CustomOption>\n        <CustomOption key={3} value={3}>\n          3rd\n        </CustomOption>\n      </select>,\n      container,\n    );\n\n    expect(container.innerHTML).toEqual(\n      '<select><option value=\"1\">1st</option><option value=\"2\">2nd</option><option value=\"3\">3rd</option></select>',\n    );\n    expect(selectElement.children[0].selected).toBe(false);\n    expect(selectElement.children[1].selected).toBe(true);\n    expect(selectElement.children[2].selected).toBe(false);\n  });\n\n  it('Should be possible to render select element with options wrapped in Fragment', () => {\n    const t = (\n      <>\n        <>\n          <option value={1}>1st</option>\n        </>\n        <option value={2}>2nd</option>\n        <>\n          <option value={3}>3rd</option>\n        </>\n      </>\n    );\n\n    render(<select value={1}>{t}</select>, container);\n\n    const selectElement = container.firstChild;\n\n    expect(container.innerHTML).toEqual(\n      '<select><option value=\"1\">1st</option><option value=\"2\">2nd</option><option value=\"3\">3rd</option></select>',\n    );\n    expect(selectElement.children[0].selected).toBe(true);\n    expect(selectElement.children[1].selected).toBe(false);\n    expect(selectElement.children[2].selected).toBe(false);\n\n    render(\n      <select value={2}>\n        <>\n          <>\n            <option value={1}>1st</option>\n          </>\n          <>\n            <option value={2}>2nd</option>\n          </>\n        </>\n        <>\n          <option value={3}>3rd</option>\n        </>\n      </select>,\n      container,\n    );\n\n    expect(container.innerHTML).toEqual(\n      '<select><option value=\"1\">1st</option><option value=\"2\">2nd</option><option value=\"3\">3rd</option></select>',\n    );\n    expect(selectElement.children[0].selected).toBe(false);\n    expect(selectElement.children[1].selected).toBe(true);\n    expect(selectElement.children[2].selected).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/setState.spec.tsx",
    "content": "import { Component, type DragEvent, render, rerender } from 'inferno';\n\ndescribe('setState', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    rerender(); // Flush pending stuff, if any\n    render(null, container);\n    document.body.removeChild(container);\n    container.innerHTML = '';\n  });\n\n  it('should throw an error when setState is called in constructor', () => {\n    class TestComponent extends Component<any, any> {\n      constructor(props, context) {\n        super(props, context);\n        this.setState({\n          state: 'Something',\n        });\n      }\n\n      public render() {\n        return null;\n      }\n    }\n\n    expect(() => {\n      render(<TestComponent />, container);\n    }).toThrow(\n      new Error(\n        'Inferno Error: cannot update state via setState() in constructor. Instead, assign to `this.state` directly or define a `state = {};`',\n      ),\n    );\n  });\n\n  it('callback should be fired after state has changed', () => {\n    let counter = 0;\n    class TestComponent extends Component<any, { value: string }> {\n      public state = {\n        value: this.props.value,\n      };\n\n      constructor(props) {\n        super(props);\n        this.checkSetState = this.checkSetState.bind(this);\n      }\n\n      public checkSetState() {\n        counter++;\n        const value = this.state.value;\n        expect(value).toBe('__NEWVALUE__');\n      }\n\n      public componentWillReceiveProps(nextProps) {\n        this.setState(\n          {\n            value: nextProps.value,\n          },\n          this.checkSetState,\n        );\n      }\n\n      public render() {\n        return null;\n      }\n    }\n\n    class BaseComp extends Component<any, any> {\n      public state = {\n        value: '__OLDVALUE__',\n      };\n\n      public componentDidMount() {\n        this.setState({\n          value: '__NEWVALUE__',\n        });\n      }\n\n      public render() {\n        const value = this.state.value;\n        return <TestComponent value={value} />;\n      }\n    }\n\n    render(<BaseComp />, container);\n    expect(container.innerHTML).toBe('');\n    rerender();\n    expect(container.innerHTML).toBe('');\n    expect(counter).toBe(1);\n  });\n\n  it('Should not fail if callback is object and not function ( invalid used scenario )', () => {\n    class TestComponent extends Component<{ value: string }, any> {\n      constructor(props) {\n        super(props);\n        this.state = {\n          value: props.value,\n        };\n      }\n\n      public componentWillReceiveProps(nextProps) {\n        this.setState(\n          {\n            value: nextProps.value,\n          },\n          { foo: 'bar' } as any, // This should not break inferno\n        );\n      }\n\n      public render() {\n        return null;\n      }\n    }\n\n    class BaseComp extends Component<any, any> {\n      public state = {\n        value: '__OLDVALUE__',\n      };\n\n      public componentDidMount() {\n        this.setState({\n          value: '__NEWVALUE__',\n        });\n      }\n\n      public render() {\n        const value = this.state.value;\n        return <TestComponent value={value} />;\n      }\n    }\n\n    render(<BaseComp />, container);\n  });\n\n  it('Should have dataTransfer in dragEvent type Github #1411', () => {\n    function handleDrop(evt: DragEvent<HTMLDivElement>) {\n      return evt.dataTransfer;\n    }\n\n    render(<div onDrop={handleDrop}>1</div>, container);\n    expect(container.innerHTML).toBe('<div>1</div>');\n  });\n\n  it('Should not fail if componentDidUpdate is not defined', () => {\n    let counter = 0;\n\n    class TestComponent extends Component<{ value: string }, any> {\n      public state = {\n        value: this.props.value,\n      };\n\n      constructor(props) {\n        super(props);\n      }\n\n      public checkSetState() {\n        const value = this.state.value;\n        counter++;\n        expect(value).toBe('__NEWVALUE__');\n      }\n\n      public componentWillReceiveProps(nextProps) {\n        this.setState(\n          {\n            value: nextProps.value,\n          },\n          this.checkSetState,\n        );\n      }\n\n      public render() {\n        return null;\n      }\n    }\n\n    class BaseComp extends Component<any, any> {\n      public state = {\n        value: '__OLDVALUE__',\n      };\n\n      public componentDidMount() {\n        this.setState({\n          value: '__NEWVALUE__',\n        });\n      }\n\n      public render() {\n        const value = this.state.value;\n        return <TestComponent value={value} />;\n      }\n    }\n\n    render(<BaseComp />, container);\n    rerender();\n    expect(counter).toBe(1);\n  });\n\n  // Should work as Per react: https://jsfiddle.net/f12u8xzb/\n  // React does not get stuck\n  it('Should not get stuck in infinite loop #1', () => {\n    let doSomething;\n\n    class Parent extends Component<any, any> {\n      public state = {\n        active: false,\n        foo: 'b',\n      };\n\n      constructor(props, context) {\n        super(props, context);\n\n        this._setBar = this._setBar.bind(this);\n        doSomething = this._setActive = this._setActive.bind(this);\n      }\n\n      private _setBar() {\n        this.setState({\n          foo: 'bar',\n        });\n      }\n\n      private _setActive() {\n        this.setState({\n          active: true,\n        });\n      }\n\n      public render() {\n        return (\n          <div>\n            <div>{this.state.foo}</div>\n            {this.state.active ? (\n              <Child foo={this.state.foo} callback={this._setBar} />\n            ) : (\n              <Child foo={this.state.foo} callback={this._setActive} />\n            )}\n          </div>\n        );\n      }\n    }\n\n    class Child extends Component<{ foo: string; callback: () => void }> {\n      constructor(props, context) {\n        super(props, context);\n      }\n\n      public componentWillUpdate(nextProps) {\n        if (nextProps.foo !== 'bar') {\n          this.props.callback();\n        }\n      }\n\n      public render() {\n        return (\n          <div>\n            <div>{this.props.foo}</div>\n          </div>\n        );\n      }\n    }\n\n    render(<Parent />, container);\n    doSomething();\n    expect(container.innerHTML).toBe(\n      '<div><div>b</div><div><div>b</div></div></div>',\n    );\n    rerender();\n    expect(container.innerHTML).toBe(\n      '<div><div>bar</div><div><div>bar</div></div></div>',\n    );\n  });\n\n  // Render should work as per React\n  // https://jsfiddle.net/qb4ootgm/\n  it('Should not fail during rendering', () => {\n    let doSomething;\n\n    class Parent extends Component<any, any> {\n      public state = {\n        active: false,\n        foo: 'b',\n      };\n\n      constructor(props, context) {\n        super(props, context);\n\n        this._setBar = this._setBar.bind(this);\n        doSomething = this._setActive = this._setActive.bind(this);\n      }\n\n      public _setBar() {\n        this.setState({\n          foo: 'bar',\n        });\n      }\n\n      public _setActive() {\n        this.setState({\n          active: true,\n        });\n      }\n\n      public render() {\n        return (\n          <div>\n            <div>{this.state.foo}</div>\n            <Child foo={this.state.foo} callback={this._setBar} />\n            <Child foo={this.state.foo} callback={this._setBar} />\n            <Child foo={this.state.foo} callback={this._setBar} />\n          </div>\n        );\n      }\n    }\n\n    class Child extends Component<{ foo: string; callback: () => void }> {\n      constructor(props, context) {\n        super(props, context);\n      }\n\n      public componentWillReceiveProps(nextProps) {\n        if (nextProps.foo !== 'bar') {\n          this.setState({\n            foo: 'bbaarr',\n          });\n\n          this.props.callback();\n        }\n      }\n\n      public render() {\n        return (\n          <div>\n            <div>{this.props.foo}</div>\n          </div>\n        );\n      }\n    }\n\n    render(<Parent />, container);\n    doSomething();\n\n    expect(container.innerHTML).toBe(\n      '<div><div>b</div><div><div>b</div></div><div><div>b</div></div><div><div>b</div></div></div>',\n    );\n    rerender();\n    expect(container.innerHTML).toBe(\n      '<div><div>bar</div><div><div>bar</div></div><div><div>bar</div></div><div><div>bar</div></div></div>',\n    );\n  });\n\n  // https://jsfiddle.net/c6q9bvez/\n  it('Should not fail during rendering #2', () => {\n    let doSomething;\n\n    class Parent extends Component<any, any> {\n      public state = {\n        active: false,\n        foo: 'b',\n      };\n\n      constructor(props, context) {\n        super(props, context);\n\n        this._setBar = this._setBar.bind(this);\n        doSomething = this._setActive = this._setActive.bind(this);\n      }\n\n      private _setBar() {\n        this.setState({\n          foo: 'bar',\n        });\n      }\n\n      private _setActive() {\n        this.setState({\n          active: true,\n        });\n      }\n\n      public render() {\n        return (\n          <div>\n            <Child foo={this.state.foo} callback={this._setActive} />\n            <ChildBar\n              foo={this.state.foo}\n              onComponentWillMount={this._setBar}\n            />\n            <ChildBar foo={this.state.foo} />\n          </div>\n        );\n      }\n    }\n\n    function ChildBar({ foo }) {\n      return <div>{foo}</div>;\n    }\n\n    class Child extends Component<{ foo: string; callback: () => void }> {\n      constructor(props, context) {\n        super(props, context);\n      }\n\n      public componentWillReceiveProps(nextProps) {\n        if (nextProps.foo !== 'bar') {\n          this.setState({\n            foo: 'bbaarr',\n          });\n\n          this.props.callback();\n        }\n      }\n\n      public render() {\n        return (\n          <div>\n            <div>{this.props.foo}</div>\n          </div>\n        );\n      }\n    }\n\n    render(<Parent />, container);\n\n    expect(container.innerHTML).toBe(\n      '<div><div><div>b</div></div><div>b</div><div>b</div></div>',\n    );\n\n    doSomething();\n\n    rerender();\n\n    expect(container.innerHTML).toBe(\n      '<div><div><div>bar</div></div><div>bar</div><div>bar</div></div>',\n    );\n  });\n\n  it('Should have new state in render when changing state during componentWillReceiveProps', () => {\n    let changeFoo;\n\n    class Parent extends Component<any, any> {\n      public state = {\n        foo: 'bar',\n      };\n\n      constructor(props, context) {\n        super(props, context);\n\n        changeFoo = this.changeFoo.bind(this);\n      }\n\n      public changeFoo() {\n        this.setState({\n          foo: 'bar2',\n        });\n      }\n\n      public render() {\n        return (\n          <div>\n            <Child foo={this.state.foo} />\n          </div>\n        );\n      }\n    }\n\n    class Child extends Component<{ foo: string }, { foo: string }> {\n      public state = {\n        foo: this.props.foo,\n      };\n\n      constructor(props, context) {\n        super(props, context);\n      }\n\n      public callback() {\n        expect(container.firstChild.firstChild.innerHTML).toBe('bar2');\n      }\n\n      public componentWillReceiveProps(nextProps) {\n        if (nextProps.foo !== this.state.foo) {\n          this.setState(\n            {\n              foo: nextProps.foo,\n            },\n            this.callback,\n          );\n        }\n      }\n\n      public render() {\n        return <div>{this.state.foo}</div>;\n      }\n    }\n\n    render(<Parent />, container);\n\n    expect(container.firstChild.firstChild.innerHTML).toBe('bar');\n\n    changeFoo();\n\n    rerender();\n\n    expect(container.innerHTML).toBe('<div><div>bar2</div></div>');\n  });\n\n  it('Should have new state in render when changing state during componentWillMount and render only once', () => {\n    const spy = jasmine.createSpy('spy');\n\n    class Parent extends Component<any, any> {\n      public state = {\n        foo: 'bar',\n      };\n\n      constructor(props, context) {\n        super(props, context);\n      }\n\n      public render() {\n        return (\n          <div>\n            <Child foo={this.state.foo} />\n          </div>\n        );\n      }\n    }\n\n    let renderCount = 0;\n    class Child extends Component<{ foo: string }, { foo: string }> {\n      public state = {\n        foo: this.props.foo,\n      };\n\n      constructor(props, context) {\n        super(props, context);\n      }\n\n      public componentWillMount() {\n        this.setState(\n          {\n            foo: '1',\n          },\n          spy,\n        );\n        this.setState(\n          {\n            foo: '2',\n          },\n          spy,\n        );\n\n        this.setState(\n          {\n            foo: '3',\n          },\n          spy,\n        );\n\n        this.setState(\n          {\n            foo: '3',\n          },\n          spy,\n        );\n\n        this.setState(\n          {\n            foo: '4',\n          },\n          spy,\n        );\n      }\n\n      public render() {\n        renderCount++;\n        return <div>{this.state.foo}</div>;\n      }\n    }\n\n    render(<Parent />, container);\n\n    expect(container.firstChild.firstChild.innerHTML).toBe('4');\n    expect(spy.calls.count()).toBe(5);\n    expect(renderCount).toBe(1);\n  });\n\n  // Should work as Per react: https://jsfiddle.net/f12u8xzb/\n  // React does not get stuck\n  it('Should not get stuck in infinite loop #1 sync', () => {\n    let doSomething;\n\n    class Parent extends Component<any, any> {\n      public state = {\n        active: false,\n        foo: 'b',\n      };\n\n      constructor(props, context) {\n        super(props, context);\n\n        this._setBar = this._setBar.bind(this);\n        doSomething = this._setActive = this._setActive.bind(this);\n      }\n\n      private _setBar() {\n        this.setState({\n          foo: 'bar',\n        });\n      }\n\n      private _setActive() {\n        this.setState({\n          active: true,\n        });\n      }\n\n      public render() {\n        return (\n          <div>\n            <div>{this.state.foo}</div>\n            {this.state.active ? (\n              <Child foo={this.state.foo} callback={this._setBar} />\n            ) : (\n              <Child foo={this.state.foo} callback={this._setActive} />\n            )}\n          </div>\n        );\n      }\n    }\n\n    class Child extends Component<{ foo: string; callback: () => void }> {\n      constructor(props, context) {\n        super(props, context);\n      }\n\n      public componentWillUpdate(nextProps) {\n        if (nextProps.foo !== 'bar') {\n          this.props.callback();\n        }\n      }\n\n      public render() {\n        return (\n          <div>\n            <div>{this.props.foo}</div>\n          </div>\n        );\n      }\n    }\n\n    render(<Parent />, container);\n    doSomething();\n    expect(container.innerHTML).toBe(\n      '<div><div>b</div><div><div>b</div></div></div>',\n    );\n    rerender();\n    expect(container.innerHTML).toBe(\n      '<div><div>bar</div><div><div>bar</div></div></div>',\n    );\n  });\n\n  // Render should work as per React\n  // https://jsfiddle.net/qb4ootgm/\n  it('Should not fail during rendering sync', () => {\n    let doSomething;\n\n    class Parent extends Component<any, any> {\n      public state = {\n        active: false,\n        foo: 'b',\n      };\n\n      constructor(props, context) {\n        super(props, context);\n\n        this._setBar = this._setBar.bind(this);\n        doSomething = this._setActive = this._setActive.bind(this);\n      }\n\n      private _setBar() {\n        this.setState({\n          foo: 'bar',\n        });\n      }\n\n      private _setActive() {\n        this.setState({\n          active: true,\n        });\n      }\n\n      public render() {\n        return (\n          <div>\n            <div>{this.state.foo}</div>\n            <Child foo={this.state.foo} callback={this._setBar} />\n            <Child foo={this.state.foo} callback={this._setBar} />\n            <Child foo={this.state.foo} callback={this._setBar} />\n          </div>\n        );\n      }\n    }\n\n    class Child extends Component<{ foo: string; callback: () => void }> {\n      constructor(props, context) {\n        super(props, context);\n      }\n\n      public componentWillReceiveProps(nextProps) {\n        if (nextProps.foo !== 'bar') {\n          this.setState({\n            foo: 'bbaarr',\n          });\n\n          this.props.callback();\n        }\n      }\n\n      public render() {\n        return (\n          <div>\n            <div>{this.props.foo}</div>\n          </div>\n        );\n      }\n    }\n\n    render(<Parent />, container);\n    doSomething();\n    expect(container.innerHTML).toBe(\n      '<div><div>b</div><div><div>b</div></div><div><div>b</div></div><div><div>b</div></div></div>',\n    );\n    rerender();\n    expect(container.innerHTML).toBe(\n      '<div><div>bar</div><div><div>bar</div></div><div><div>bar</div></div><div><div>bar</div></div></div>',\n    );\n  });\n\n  it('Should be possible to update state in componentWillUpdate', () => {\n    interface MyState {\n      foo: string;\n    }\n\n    class Hello extends Component<any, MyState> {\n      constructor(p, c) {\n        super(p, c);\n\n        this.state = {\n          foo: 'je',\n        };\n      }\n\n      public componentWillUpdate() {\n        if (this.state!.foo === 'je') {\n          this.setState({\n            foo: 'bar',\n          });\n        }\n      }\n\n      public render() {\n        return <div>Hello {this.state!.foo}</div>;\n      }\n    }\n\n    expect(container.innerHTML).toBe('');\n\n    render(<Hello name=\"World\" />, container);\n\n    expect(container.innerHTML).toBe('<div>Hello je</div>');\n\n    render(<Hello name=\"World\" />, container);\n\n    rerender();\n\n    expect(container.innerHTML).toBe('<div>Hello bar</div>');\n  });\n\n  it('setState must be sync like React if no state changes are pending', () => {\n    let doSomething;\n\n    class Parent extends Component<any, any> {\n      public state = {\n        foo: 'b',\n      };\n\n      constructor(props, context) {\n        super(props, context);\n\n        doSomething = this._setBar = this._setBar.bind(this);\n      }\n\n      private _setBar(p) {\n        this.setState({\n          foo: p,\n        });\n      }\n\n      public render() {\n        return <div>{this.state.foo}</div>;\n      }\n    }\n\n    render(<Parent />, container);\n    // Set state must go sync when nothing pending\n    expect(container.firstChild.innerHTML).toBe('b');\n    doSomething('1');\n    expect(container.firstChild.innerHTML).toBe('1');\n    doSomething('2');\n    expect(container.firstChild.innerHTML).toBe('2');\n    doSomething('3');\n    expect(container.firstChild.innerHTML).toBe('3');\n    doSomething('4');\n    expect(container.firstChild.innerHTML).toBe('4');\n  });\n\n  it('Set state callback should have context of caller component (forced) - as per React', () => {\n    let cnt = 0;\n\n    class Com extends Component<any, any> {\n      public doTest() {\n        expect(this.state!.a).toBe(cnt);\n      }\n\n      public componentWillMount() {\n        this.setState(\n          {\n            a: ++cnt,\n          },\n          this.doTest,\n        );\n      }\n\n      public componentDidMount() {\n        this.setState(\n          {\n            a: ++cnt,\n          },\n          this.doTest,\n        );\n      }\n\n      public render() {\n        return <div>1</div>;\n      }\n    }\n\n    render(<Com />, container);\n  });\n\n  it('Should not re-create state if no setState is called', () => {\n    const FooBarState = [1];\n\n    class FooBar extends Component<any, any> {\n      constructor(props, context) {\n        super(props, context);\n\n        this.state = FooBarState;\n      }\n\n      public render(_props, state) {\n        expect(state).toBe(FooBarState);\n        expect(this.state).toBe(FooBarState);\n        expect(state === FooBarState).toBe(true);\n\n        return <div>{state[0]}</div>;\n      }\n    }\n\n    render(<FooBar />, container);\n\n    expect(container.innerHTML).toEqual('<div>1</div>');\n\n    render(<FooBar />, container);\n\n    expect(container.innerHTML).toEqual('<div>1</div>');\n  });\n\n  it('Should keep context in sync with state #1182', () => {\n    function Child(_props, context) {\n      return (\n        <div>\n          {(context.active ? 'ACTIVE' : 'INACTIVE') +\n            '   :   ' +\n            (context.state.active ? 'ACTIVE' : 'INACTIVE')}\n        </div>\n      );\n    }\n\n    class Container extends Component<\n      { active: boolean },\n      { active: boolean }\n    > {\n      public state = {\n        active: false,\n      };\n\n      constructor(props, context) {\n        super(props, context);\n      }\n\n      public getChildContext() {\n        return {\n          active: this.state.active,\n          state: this.state,\n        };\n      }\n\n      public componentWillReceiveProps(nextProps) {\n        if (this.state.active !== nextProps.active) {\n          this.setState({\n            active: nextProps.active,\n          });\n        }\n      }\n\n      public render() {\n        return <Child />;\n      }\n    }\n\n    let updater;\n    class App extends Component<any, any> {\n      public state = {\n        active: false,\n      };\n\n      constructor(props, context) {\n        super(props, context);\n\n        updater = this.didClick.bind(this);\n      }\n\n      public didClick() {\n        this.setState({\n          active: !this.state.active,\n        });\n      }\n\n      public render() {\n        return (\n          <div>\n            <Container active={this.state.active} />\n          </div>\n        );\n      }\n    }\n\n    render(<App />, container);\n\n    expect(container.textContent).toBe('INACTIVE   :   INACTIVE');\n\n    updater();\n    rerender();\n\n    expect(container.textContent).toBe('ACTIVE   :   ACTIVE');\n\n    updater();\n    rerender();\n\n    expect(container.textContent).toBe('INACTIVE   :   INACTIVE');\n\n    updater();\n    rerender();\n\n    expect(container.textContent).toBe('ACTIVE   :   ACTIVE');\n  });\n\n  it('Should call all setState callbacks', () => {\n    let counter = 0;\n    let setStateCounter = 0;\n\n    class Child extends Component<any, any> {\n      constructor(props) {\n        super(props);\n        this.state = { test: false };\n        this.callCallback = this.callCallback.bind(this);\n      }\n\n      public callCallback() {\n        setStateCounter++;\n        this.setState({ test: true }, () => {\n          counter++;\n        });\n      }\n\n      public render() {\n        if (setStateCounter === 1) {\n          this.callCallback();\n          this.props.callback(true);\n        }\n\n        return <div>Child</div>;\n      }\n    }\n\n    class MidChild extends Component<any, any> {\n      constructor(props) {\n        super(props);\n        this.state = { test: false };\n        this.callCallback = this.callCallback.bind(this);\n      }\n\n      public callCallback() {\n        setStateCounter++;\n        this.setState({ test: true }, () => {\n          counter++;\n          this.props.callback(true);\n        });\n      }\n\n      public render() {\n        return [\n          <button onClick={this.callCallback}>Click</button>,\n          <Child callback={this.props.callback} />,\n        ];\n      }\n    }\n\n    class Parent extends Component<any, any> {\n      constructor(props) {\n        super(props);\n        this.state = { test: false, foobar: false };\n        this.doSomething = this.doSomething.bind(this);\n        this.callCallback = this.callCallback.bind(this);\n      }\n\n      public callCallback(testValue) {\n        setStateCounter++;\n        this.setState({ test: testValue }, () => {\n          counter++;\n          this.props.callback(true);\n        });\n      }\n\n      public doSomething() {\n        setStateCounter++;\n        this.setState({ foobar: true }, () => {\n          counter++;\n        });\n      }\n\n      public render() {\n        return (\n          <div>\n            <MidChild\n              callback={this.callCallback}\n              foobar={this.state!.foobar}\n            />\n          </div>\n        );\n      }\n    }\n\n    class Wrapper extends Component<any, any> {\n      constructor(props) {\n        super(props);\n        this.state = { didCounter: 0 };\n        this.doSomething = this.doSomething.bind(this);\n      }\n\n      public doSomething() {\n        setStateCounter++;\n\n        this.setState({ didCounter: this.state!.didCounter + 1 }, () => {\n          counter++;\n        });\n      }\n\n      public render() {\n        return (\n          <div>\n            <Parent callback={this.doSomething} />\n            <span>{this.state!.didCounter}</span>\n          </div>\n        );\n      }\n    }\n\n    render(<Wrapper />, container);\n\n    expect(counter).toBe(0);\n    expect(setStateCounter).toBe(0);\n\n    const btn = container.querySelector('button');\n\n    btn.click();\n\n    rerender();\n    expect(setStateCounter).toBe(6);\n    expect(counter).toBe(6);\n\n    expect(container.innerHTML).toEqual(\n      '<div><div><button>Click</button><div>Child</div></div><span>2</span></div>',\n    );\n  });\n\n  it('Should update setState callback argument - Github #1420', () => {\n    let renderCounter = 0;\n\n    interface TextState {\n      texts: {\n        text1: string;\n        text2: string;\n        text3: string;\n      };\n    }\n\n    class BrokenComponent extends Component<any, TextState> {\n      constructor(props, context) {\n        super(props, context);\n        this.state = {\n          texts: {\n            text1: 'Initial text 1',\n            text2: 'Initial text 2',\n            text3: 'Initial text 3',\n          },\n        };\n      }\n\n      public componentDidMount() {\n        // This change is ignored\n        this.setState((prevState) => {\n          // init all\n          return {\n            texts: {\n              ...prevState.texts,\n              text1: 'Updated text 1',\n            },\n          };\n        });\n        // This change is also ignored\n        this.setState((prevState) => {\n          return {\n            texts: {\n              ...prevState.texts,\n              text2: 'Updated text 2',\n            },\n          };\n        });\n        // Only this change is applied\n        this.setState((prevState) => {\n          return {\n            texts: {\n              ...prevState.texts,\n              text3: 'Updated text 3',\n            },\n          };\n        });\n      }\n\n      public render() {\n        const { text1, text2, text3 } = this.state!.texts;\n\n        renderCounter++;\n\n        return (\n          <ul>\n            <li>{text1}</li>\n            <li>{text2}</li>\n            <li>{text3}</li>\n          </ul>\n        );\n      }\n    }\n\n    expect(renderCounter).toBe(0);\n\n    render(<BrokenComponent />, container);\n\n    expect(renderCounter).toBe(1);\n\n    expect(container.innerHTML).toBe(\n      '<ul><li>Initial text 1</li><li>Initial text 2</li><li>Initial text 3</li></ul>',\n    );\n\n    rerender();\n\n    expect(renderCounter).toBe(2);\n\n    expect(container.innerHTML).toBe(\n      '<ul><li>Updated text 1</li><li>Updated text 2</li><li>Updated text 3</li></ul>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/singlepatches.spec.tsx",
    "content": "import { Component, Fragment, render } from 'inferno';\n\ndescribe('All single patch variations', () => {\n  let templateRefSpy;\n  let container;\n  let mountSpy;\n  let updateSpy;\n  let unmountSpy;\n\n  beforeEach(function () {\n    mountSpy = spyOn(ComA.prototype, 'componentWillMount');\n    updateSpy = spyOn(ComA.prototype, 'componentWillUpdate');\n    unmountSpy = spyOn(ComA.prototype, 'componentWillUnmount');\n    templateRefSpy = jasmine.createSpy('spy');\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  function rTemplate(content) {\n    render(<div>{[content]}</div>, container);\n  }\n\n  function tearDown() {\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n  }\n\n  class ComA extends Component<any, any> {\n    public componentDidMount() {}\n\n    public componentWillMount() {}\n\n    public componentWillReceiveProps(_nextProps, _nextContext) {}\n\n    public shouldComponentUpdate(_nextProps, _nextState, _nextContext) {\n      return true;\n    }\n\n    public componentWillUpdate(_nextProps, _nextState, _nextContext) {}\n\n    public componentDidUpdate(_prevProps, _prevState, _prevContext) {}\n\n    public componentWillUnmount() {}\n\n    public render({ children }) {\n      return children;\n    }\n  }\n\n  describe('Text to', () => {\n    let node;\n\n    beforeEach(() => {\n      rTemplate('text');\n      expect(container.innerHTML).toEqual('<div>text</div>');\n      node = container.firstChild.firstChild;\n    });\n\n    it('text', () => {\n      rTemplate('more text');\n      expect(container.innerHTML).toEqual('<div>more text</div>');\n\n      expect(container.firstChild.firstChild).toBe(node);\n\n      rTemplate('more text2');\n      expect(container.innerHTML).toEqual('<div>more text2</div>');\n\n      expect(container.firstChild.firstChild).toBe(node);\n      tearDown();\n    });\n\n    it('invalid', () => {\n      rTemplate(false);\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      expect(container.firstChild.firstChild).toBe(null);\n\n      rTemplate(null);\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      expect(container.firstChild.firstChild).toBe(null);\n      tearDown();\n    });\n\n    it('vNode (elem)', () => {\n      const spy = jasmine.createSpy('spy');\n\n      rTemplate(<span ref={spy}>1</span>);\n      expect(container.innerHTML).toEqual('<div><span>1</span></div>');\n\n      expect(spy.calls.count()).toBe(1);\n\n      rTemplate(<span ref={spy}>2</span>);\n      expect(container.innerHTML).toEqual('<div><span>2</span></div>');\n\n      expect(spy.calls.count()).toBe(1);\n      tearDown();\n    });\n\n    it('vNode (com)', () => {\n      const spy = jasmine.createSpy('spy');\n\n      rTemplate(<ComA ref={spy}>1</ComA>);\n      expect(container.innerHTML).toEqual('<div>1</div>');\n      expect(mountSpy.calls.count()).toBe(1);\n      expect(updateSpy.calls.count()).toBe(0);\n      expect(unmountSpy.calls.count()).toBe(0);\n      expect(spy.calls.count()).toBe(1);\n\n      rTemplate(<ComA ref={spy}>2</ComA>);\n      expect(container.innerHTML).toEqual('<div>2</div>');\n      expect(mountSpy.calls.count()).toBe(1);\n      expect(updateSpy.calls.count()).toBe(1);\n      expect(unmountSpy.calls.count()).toBe(0);\n      expect(spy.calls.count()).toBe(1);\n\n      tearDown();\n    });\n\n    it('Array', () => {\n      const spy = jasmine.createSpy('spy');\n\n      rTemplate([<ComA ref={spy}>1</ComA>, 'foo']);\n      expect(container.innerHTML).toEqual('<div>1foo</div>');\n      expect(mountSpy.calls.count()).toBe(1);\n      expect(updateSpy.calls.count()).toBe(0);\n      expect(unmountSpy.calls.count()).toBe(0);\n      expect(spy.calls.count()).toBe(1);\n\n      rTemplate([<ComA ref={spy}>2</ComA>, null]);\n      expect(container.innerHTML).toEqual('<div>2</div>');\n      expect(mountSpy.calls.count()).toBe(1);\n      expect(updateSpy.calls.count()).toBe(1);\n      expect(unmountSpy.calls.count()).toBe(0);\n      expect(spy.calls.count()).toBe(1);\n\n      tearDown();\n    });\n  });\n\n  describe('Component to', () => {\n    beforeEach(() => {\n      rTemplate(<ComA ref={templateRefSpy}>first</ComA>);\n      expect(templateRefSpy.calls.count()).toBe(1);\n      templateRefSpy.calls.reset();\n      expect(container.innerHTML).toEqual('<div>first</div>');\n      expect(unmountSpy.calls.count()).toBe(0);\n      expect(mountSpy.calls.count()).toBe(1);\n      expect(updateSpy.calls.count()).toBe(0);\n    });\n\n    it('text', () => {\n      rTemplate('more text');\n      expect(container.innerHTML).toEqual('<div>more text</div>');\n      expect(unmountSpy.calls.count()).toBe(1);\n      expect(mountSpy.calls.count()).toBe(1);\n      expect(updateSpy.calls.count()).toBe(0);\n\n      rTemplate('more text2');\n      expect(container.innerHTML).toEqual('<div>more text2</div>');\n      tearDown();\n    });\n\n    it('invalid', () => {\n      rTemplate(false);\n      expect(container.innerHTML).toEqual('<div></div>');\n      expect(unmountSpy.calls.count()).toBe(1);\n      expect(mountSpy.calls.count()).toBe(1);\n      expect(updateSpy.calls.count()).toBe(0);\n\n      expect(container.firstChild.firstChild).toBe(null);\n\n      rTemplate(null);\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      expect(container.firstChild.firstChild).toBe(null);\n      tearDown();\n    });\n\n    it('vNode (elem)', () => {\n      const spy = jasmine.createSpy('spy');\n      expect(templateRefSpy.calls.count()).toBe(0);\n\n      rTemplate(\n        <div ref={spy} className=\"component2\">\n          Component 2 <br />\n          <span id=\"clear\">clear app</span>\n        </div>,\n      );\n      expect(templateRefSpy.calls.count()).toBe(1); // unmount\n      expect(unmountSpy.calls.count()).toBe(1);\n      expect(spy.calls.count()).toBe(1);\n      expect(updateSpy.calls.count()).toBe(0);\n      expect(container.innerHTML).toEqual(\n        '<div><div class=\"component2\">Component 2 <br><span id=\"clear\">clear app</span></div></div>',\n      );\n\n      rTemplate(<span ref={spy}>2</span>);\n      expect(container.innerHTML).toEqual('<div><span>2</span></div>');\n\n      expect(spy.calls.count()).toBe(3); // mount, unmount, mount\n      tearDown();\n    });\n\n    it('vNode (Com different)', () => {\n      const componentWillMountSpy = jasmine.createSpy();\n\n      class ComC extends Component<any, any> {\n        componentWillMount() {\n          componentWillMountSpy();\n        }\n\n        public render({ children }) {\n          return children;\n        }\n      }\n\n      rTemplate(<ComC>second</ComC>);\n\n      expect(componentWillMountSpy).toHaveBeenCalledTimes(1);\n\n      tearDown();\n    });\n  });\n\n  describe('children', () => {\n    describe('HasKeyedChildren', () => {\n      it('Should update from Array to single vNode', () => {\n        render(\n          <div $HasKeyedChildren>\n            {[<div key=\"1\">1</div>, <div key=\"2\">2</div>]}\n          </div>,\n          container,\n        );\n\n        expect(container.innerHTML).toEqual(\n          '<div><div>1</div><div>2</div></div>',\n        );\n\n        render(\n          <div>\n            <div>single</div>\n          </div>,\n          container,\n        );\n\n        expect(container.innerHTML).toEqual('<div><div>single</div></div>');\n\n        // Revert\n        render(\n          <div $HasKeyedChildren>\n            {[<div key=\"1\">1</div>, <div key=\"2\">2</div>]}\n          </div>,\n          container,\n        );\n\n        expect(container.innerHTML).toEqual(\n          '<div><div>1</div><div>2</div></div>',\n        );\n      });\n    });\n\n    describe('hasNonKeyedChildren', () => {\n      it('Should update from Array to single vNode', () => {\n        render(\n          <div $HasNonKeyedChildren>{[<div>1</div>, <div>2</div>]}</div>,\n          container,\n        );\n\n        expect(container.innerHTML).toEqual(\n          '<div><div>1</div><div>2</div></div>',\n        );\n\n        render(\n          <div>\n            <div>single</div>\n          </div>,\n          container,\n        );\n\n        expect(container.innerHTML).toEqual('<div><div>single</div></div>');\n\n        // Revert\n        render(\n          <div $HasNonKeyedChildren>{[<div>1</div>, <div>2</div>]}</div>,\n          container,\n        );\n\n        expect(container.innerHTML).toEqual(\n          '<div><div>1</div><div>2</div></div>',\n        );\n      });\n    });\n  });\n\n  describe('defaultHooks', () => {\n    it('Should never update if defaultProps refs SCU returns false', () => {\n      let counter = 0;\n\n      const Static = function () {\n        return <div>{counter}</div>;\n      };\n\n      Static.defaultHooks = {\n        onComponentShouldUpdate() {\n          return false;\n        },\n      };\n\n      function doRender() {\n        render(\n          <div>\n            {counter}\n            <Static />\n          </div>,\n          container,\n        );\n      }\n\n      doRender();\n      expect(container.innerHTML).toEqual('<div>0<div>0</div></div>');\n      counter++;\n      doRender();\n      expect(container.innerHTML).toEqual('<div>1<div>0</div></div>');\n      counter++;\n      doRender();\n      expect(container.innerHTML).toEqual('<div>2<div>0</div></div>');\n    });\n\n    it('Should prefer external hook if given', () => {\n      let counter = 0;\n      let mountCounter = 0;\n\n      interface scuTestType {\n        onComponentShouldUpdate: () => boolean;\n      }\n\n      const Static = function (_: scuTestType) {\n        return <div>{counter}</div>;\n      };\n\n      Static.defaultHooks = {\n        onComponentShouldUpdate() {\n          return false;\n        },\n        onComponentWillMount() {\n          mountCounter++;\n        },\n      };\n\n      function doRender() {\n        render(\n          <div>\n            {counter}\n            <Static onComponentShouldUpdate={() => true} />\n          </div>,\n          container,\n        );\n      }\n\n      doRender();\n      expect(container.innerHTML).toEqual('<div>0<div>0</div></div>');\n      counter++;\n      expect(mountCounter).toBe(1);\n      doRender();\n      expect(container.innerHTML).toEqual('<div>1<div>1</div></div>');\n      counter++;\n      expect(mountCounter).toBe(1);\n      doRender();\n      expect(container.innerHTML).toEqual('<div>2<div>2</div></div>');\n      expect(mountCounter).toBe(1);\n    });\n\n    it('Should be possible to define default hooks and use spread operator', () => {\n      let counter = 0;\n      let mountCounter = 0;\n\n      const Static = function () {\n        return <div>{counter}</div>;\n      };\n\n      Static.defaultHooks = {\n        onComponentShouldUpdate() {\n          return false;\n        },\n        onComponentWillMount() {\n          mountCounter++;\n        },\n      };\n\n      const props = {\n        ref: {\n          onComponentShouldUpdate: () => true,\n        },\n      };\n\n      // TODO: Supporting types for \"ref: {}\" function component hooks probably needs changes to \"JSX root types\" where are those?\n\n      function doRender() {\n        render(\n          <div>\n            {counter}\n            {/*\n // @ts-expect-error */}\n            <Static {...props} />\n          </div>,\n          container,\n        );\n      }\n\n      doRender();\n      expect(container.innerHTML).toEqual('<div>0<div>0</div></div>');\n      counter++;\n      expect(mountCounter).toBe(1);\n      doRender();\n      expect(container.innerHTML).toEqual('<div>1<div>1</div></div>');\n      counter++;\n      expect(mountCounter).toBe(1);\n      doRender();\n      expect(container.innerHTML).toEqual('<div>2<div>2</div></div>');\n      expect(mountCounter).toBe(1);\n    });\n  });\n\n  describe('immutable children', () => {\n    it('Should be possible to render frozen objects', () => {\n      const EMPTY_ARRAY = [];\n      Object.freeze(EMPTY_ARRAY);\n\n      render(<div>{EMPTY_ARRAY}</div>, container);\n\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(<div>{EMPTY_ARRAY}</div>, container);\n\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(<div>{EMPTY_ARRAY}</div>, container);\n\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(<div>{null}</div>, container);\n      expect(container.innerHTML).toBe('<div></div>');\n    });\n\n    it('Should be possible to render frozen objects #2', () => {\n      const EMPTY_ARRAY = [];\n      const TWO_NODES = [<div>1</div>, <div>2</div>];\n      Object.freeze(EMPTY_ARRAY);\n      Object.freeze(TWO_NODES);\n\n      render(<div>{EMPTY_ARRAY}</div>, container);\n\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(<div>{TWO_NODES}</div>, container);\n\n      expect(container.innerHTML).toBe('<div><div>1</div><div>2</div></div>');\n\n      render(<div>{EMPTY_ARRAY}</div>, container);\n\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(<div>{null}</div>, container);\n      expect(container.innerHTML).toBe('<div></div>');\n    });\n  });\n\n  describe('it should use non keyed algorithm if its forced Github #1275', () => {\n    it('last & prev are flagged $HasNonKeyedChildren', () => {\n      render(\n        <div $HasNonKeyedChildren>\n          {[<div key=\"1\">1</div>, <div key=\"2\">2</div>]}\n        </div>,\n        container,\n      );\n\n      const oldFirstNode = container.firstChild.firstChild;\n      expect(container.innerHTML).toBe('<div><div>1</div><div>2</div></div>');\n\n      render(\n        <div $HasNonKeyedChildren>\n          {[<div key=\"2\">2</div>, <div key=\"1\">1</div>]}\n        </div>,\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div><div>2</div><div>1</div></div>');\n\n      // It is forced to do non keyed, so elements are remounted\n      expect(container.firstChild.firstChild).not.toBe(oldFirstNode);\n    });\n  });\n\n  it('Should remount whole vNode tree when parent element vNode key changes', () => {\n    let mountCallCount = 0;\n    let unmountCallCount = 0;\n\n    class ComponentFooBar extends Component<any, any> {\n      public componentWillMount() {\n        mountCallCount++;\n      }\n\n      public componentWillUnmount() {\n        unmountCallCount++;\n      }\n\n      public render() {\n        return <div>Component</div>;\n      }\n    }\n\n    render(\n      <div>\n        <div key=\"First\">\n          <ComponentFooBar />\n        </div>\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toEqual(\n      '<div><div><div>Component</div></div></div>',\n    );\n\n    expect(mountCallCount).toBe(1);\n    expect(unmountCallCount).toBe(0);\n\n    render(\n      <div>\n        <div key=\"Another\">\n          <ComponentFooBar />\n        </div>\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toEqual(\n      '<div><div><div>Component</div></div></div>',\n    );\n\n    expect(mountCallCount).toBe(2);\n    expect(unmountCallCount).toBe(1);\n  });\n\n  it('Should handle situation where same element ref is used multiple times', () => {\n    const div = <div>Fun</div>;\n\n    render(\n      <Fragment $HasNonKeyedChildren>\n        {[\n          div,\n          div,\n          <div $HasNonKeyedChildren>\n            {div}\n            <div $HasVNodeChildren>{div}</div>\n          </div>,\n          div,\n        ]}\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div>Fun</div><div>Fun</div><div><div>Fun</div><div><div>Fun</div></div></div><div>Fun</div>',\n    );\n\n    expect(container.$V.children[1].children[0]).not.toBe(\n      container.$V.children[0],\n    );\n    expect(container.$V.children[0]).not.toBe(container.$V.children[3]);\n\n    render(\n      <Fragment $HasNonKeyedChildren>\n        {[\n          div,\n          div,\n          <div $HasNonKeyedChildren>\n            {div}\n            <div $HasVNodeChildren>{div}</div>\n            {div}\n          </div>,\n          div,\n        ]}\n      </Fragment>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div>Fun</div><div>Fun</div><div><div>Fun</div><div><div>Fun</div></div><div>Fun</div></div><div>Fun</div>',\n    );\n    expect(container.$V.children[0]).not.toBe(container.$V.children[3]);\n  });\n\n  it('Should unmount root fragment with hoisted children', () => {\n    const div = <div>Fun</div>;\n\n    render(\n      <Fragment $HasNonKeyedChildren>\n        {[\n          div,\n          div,\n          div,\n          <div $HasNonKeyedChildren>\n            {div}\n            <div $HasVNodeChildren>{div}</div>\n            {div}\n          </div>,\n          div,\n          div,\n          div,\n        ]}\n      </Fragment>,\n      container,\n    );\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n\n    render(null, container);\n    render(null, container);\n  });\n\n  it('Should handle hoisted nodes correctly', () => {\n    const div = <div>Fun</div>;\n\n    function Okay() {\n      return div;\n    }\n\n    const OkayHoisted = <Okay />;\n\n    function Nested() {\n      return OkayHoisted;\n    }\n\n    class Foobar extends Component {\n      public render() {\n        return (\n          <>\n            {div}\n            <span>Ok</span>\n            <Okay />\n          </>\n        );\n      }\n    }\n\n    const NestedHoisted = <Nested />;\n    const FooBarHoisted = <Foobar />;\n\n    render(\n      <Fragment>\n        {[\n          FooBarHoisted,\n          <Foobar />,\n          div,\n          <div>\n            {NestedHoisted}\n            <div>{div}</div>\n            {NestedHoisted}\n          </div>,\n          FooBarHoisted,\n          div,\n          div,\n        ]}\n      </Fragment>,\n      container,\n    );\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n\n    render(null, container);\n    render(null, container);\n  });\n\n  it('Should not re-mount fragment contents', () => {\n    class Foobar extends Component<\n      any,\n      {\n        val: number;\n      }\n    > {\n      public state = {\n        val: 1,\n      };\n\n      constructor(props, context) {\n        super(props, context);\n      }\n\n      public render() {\n        return (\n          <div\n            onClick={() => {\n              this.setState({ val: this.state.val + 1 });\n            }}\n          >\n            <span>{this.state.val}</span>\n            {this.props.children}\n          </div>\n        );\n      }\n    }\n\n    function Foobar2(props) {\n      return <span className={props.data}>Foo</span>;\n    }\n\n    render(\n      <>\n        <Foobar>\n          <div>\n            <Foobar2 data=\"first\" />\n          </div>\n          <>\n            <>\n              <Foobar2 data=\"second\" />\n              <Foobar2 data=\"third\" />\n            </>\n          </>\n        </Foobar>\n      </>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><span>1</span><div><span class=\"first\">Foo</span></div><span class=\"second\">Foo</span><span class=\"third\">Foo</span></div>',\n    );\n\n    const firstNode = container.querySelector('.first');\n    const secondNode = container.querySelector('.second');\n\n    container.firstChild.click();\n\n    expect(container.innerHTML).toBe(\n      '<div><span>2</span><div><span class=\"first\">Foo</span></div><span class=\"second\">Foo</span><span class=\"third\">Foo</span></div>',\n    );\n\n    expect(container.querySelector('.first')).toBe(firstNode);\n    expect(container.querySelector('.second')).toBe(secondNode);\n\n    container.firstChild.click();\n\n    expect(container.innerHTML).toBe(\n      '<div><span>3</span><div><span class=\"first\">Foo</span></div><span class=\"second\">Foo</span><span class=\"third\">Foo</span></div>',\n    );\n\n    expect(container.querySelector('.first')).toBe(firstNode);\n    expect(container.querySelector('.second')).toBe(secondNode);\n  });\n\n  it('Should keep given key even for deeply nested content', () => {\n    render(\n      <div>\n        {[null, <div key=\"first\">First</div>, <div key=\"second\">Second</div>]}\n      </div>,\n      container,\n    );\n\n    const firstDiv = container.firstChild.firstChild;\n    const secondDiv = container.firstChild.childNodes[1];\n\n    expect(container.innerHTML).toBe(\n      '<div><div>First</div><div>Second</div></div>',\n    );\n\n    render(\n      <div>\n        {[\n          null,\n          undefined,\n          <div key=\"first\">First</div>,\n          <div key=\"second\">Second</div>,\n        ]}\n      </div>,\n      container,\n    );\n    const firstDiv2 = container.firstChild.firstChild;\n    const secondDiv2 = container.firstChild.childNodes[1];\n\n    expect(container.innerHTML).toBe(\n      '<div><div>First</div><div>Second</div></div>',\n    );\n\n    expect(firstDiv).toBe(firstDiv2);\n    expect(secondDiv).toBe(secondDiv2);\n  });\n\n  it('Should keep given key even for deeply nested content #2', () => {\n    const vNode1 = <div key=\"first\">First</div>;\n\n    render(\n      <div>\n        {[\n          null,\n          <div key=\"first1\">First</div>,\n          vNode1,\n          <div key=\"second\">Second</div>,\n        ]}\n      </div>,\n      container,\n    );\n\n    const domNode = container.firstChild.childNodes[1];\n\n    expect(container.innerHTML).toBe(\n      '<div><div>First</div><div>First</div><div>Second</div></div>',\n    );\n\n    render(\n      <div>\n        {[\n          null,\n          undefined,\n          <div key=\"first1\">First</div>,\n          [vNode1],\n          <div key=\"second\">Second</div>,\n        ]}\n      </div>,\n      container,\n    );\n    const domNode2 = container.firstChild.childNodes[1];\n\n    expect(container.innerHTML).toBe(\n      '<div><div>First</div><div>First</div><div>Second</div></div>',\n    );\n\n    expect(domNode).not.toBe(domNode2);\n  });\n\n  it('Should differenciate between location even if key is same', () => {\n    let changeState: any = null;\n    const okDiv = <div key=\"ok\">ok</div>;\n\n    class Example extends Component<{\n      test: boolean;\n    }> {\n      constructor(props, context) {\n        super(props, context);\n\n        changeState = () => {\n          this.setState({});\n        };\n      }\n\n      public render() {\n        if (this.props.test) {\n          return <div>{[[[[[[okDiv]]]]]]}</div>;\n        }\n\n        return <div>{[[okDiv]]}</div>;\n      }\n    }\n    render(<Example test={false} />, container);\n\n    const domNode = container.firstChild.childNodes[0];\n\n    changeState();\n\n    // set state should keep it the same\n    expect(domNode).toBe(container.firstChild.childNodes[0]);\n\n    render(<Example test={true} />, container);\n\n    // Rendered to different array, create new dom\n    const newDomNode = container.firstChild.childNodes[0];\n\n    expect(newDomNode).not.toBe(domNode);\n\n    changeState();\n\n    expect(newDomNode).toBe(container.firstChild.childNodes[0]);\n  });\n\n  it('Should differenciate between location even if key is same (props.children)', () => {\n    let changeState: any = null;\n\n    class Example extends Component<{\n      test: boolean;\n    }> {\n      constructor(props, context) {\n        super(props, context);\n\n        changeState = () => {\n          this.setState({});\n        };\n      }\n\n      public render() {\n        if (this.props.test) {\n          return <div>{[[[[[[this.props.children]]]]]]}</div>;\n        }\n\n        return <div>{[[this.props.children]]}</div>;\n      }\n    }\n\n    function start(bool: boolean) {\n      render(\n        <Example test={bool}>\n          <div key=\"ok\">ok</div>\n        </Example>,\n        container,\n      );\n    }\n\n    start(false);\n\n    const domNode = container.firstChild.childNodes[0];\n\n    changeState();\n\n    // set state should keep it the same\n    expect(domNode).toBe(container.firstChild.childNodes[0]);\n\n    start(true);\n\n    // Rendered to different array, create new dom\n    const newDomNode = container.firstChild.childNodes[0];\n\n    expect(newDomNode).not.toBe(domNode);\n\n    changeState();\n\n    expect(newDomNode).toBe(container.firstChild.childNodes[0]);\n  });\n\n  it('Should not recreate DOM nodes if key is given and does not change', () => {\n    let changeState: any = null;\n\n    class Example extends Component {\n      constructor(props, context) {\n        super(props, context);\n\n        changeState = () => {\n          this.setState({});\n        };\n      }\n\n      public render() {\n        return (\n          <div key=\"exampleDiv\">\n            <input key=\"button\" type=\"button\" value=\"rerender\" />\n            {this.props.children}\n          </div>\n        );\n      }\n    }\n\n    const rerender = function () {\n      // children must be defiend outside the Exampe Component\n      // if defined insite render of Exampe and/or its a single child, there is no issue\n      render(\n        <Example key=\"exmapleApp\">\n          <div class=\"anim1\" key=\"div1\" />\n          <div class=\"anim2\" key=\"div22\" />\n        </Example>,\n        container,\n      );\n    };\n\n    rerender();\n\n    const originalInput = container.firstChild.children[0];\n    const originalDiv1 = container.firstChild.children[1];\n    const originalDiv2 = container.firstChild.children[2];\n\n    changeState();\n\n    expect(originalInput).toBe(container.firstChild.children[0]);\n    expect(originalDiv1).toBe(container.firstChild.children[1]);\n    expect(originalDiv2).toBe(container.firstChild.children[2]);\n\n    changeState();\n\n    expect(originalInput).toBe(container.firstChild.children[0]);\n    expect(originalDiv1).toBe(container.firstChild.children[1]);\n    expect(originalDiv2).toBe(container.firstChild.children[2]);\n\n    rerender();\n\n    expect(originalInput).toBe(container.firstChild.children[0]);\n    expect(originalDiv1).toBe(container.firstChild.children[1]);\n    expect(originalDiv2).toBe(container.firstChild.children[2]);\n\n    changeState();\n\n    expect(originalInput).toBe(container.firstChild.children[0]);\n    expect(originalDiv1).toBe(container.firstChild.children[1]);\n    expect(originalDiv2).toBe(container.firstChild.children[2]);\n\n    rerender();\n\n    expect(originalInput).toBe(container.firstChild.children[0]);\n    expect(originalDiv1).toBe(container.firstChild.children[1]);\n    expect(originalDiv2).toBe(container.firstChild.children[2]);\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/state.spec.tsx",
    "content": "import { Component, createComponentVNode, render, rerender } from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nlet renderCount = 0;\n\nclass TestCWRP extends Component<any, any> {\n  public state = {\n    a: 0,\n    b: 0,\n  };\n\n  constructor(props) {\n    super(props);\n  }\n\n  public componentWillReceiveProps() {\n    this.setState({ a: 1 });\n\n    expect(this.state.a).toBe(0); // It should be 0 because state is not synchronously updated\n  }\n\n  public render() {\n    if (renderCount === 0) {\n      expect(this.state.a).toBe(0);\n    } else if (renderCount === 1) {\n      expect(this.state.a).toBe(1); // Changed in CWRP\n    }\n\n    renderCount++;\n\n    return <div>{JSON.stringify(this.state)}</div>;\n  }\n}\n\ndescribe('state', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  // As per React\n  it('Should not have state defined in base constructor', () => {\n    class Foo extends Component<any, any> {\n      constructor(p, c) {\n        super(p, c);\n\n        expect(this.state).toBeNull();\n      }\n\n      public render() {\n        return null;\n      }\n    }\n\n    const f = new Foo({}, {});\n\n    expect(f).not.toBeNull();\n  });\n\n  describe('setting state', () => {\n    it('setState should apply state during componentWillReceiveProps', (done) => {\n      render(\n        createComponentVNode(VNodeFlags.ComponentClass, TestCWRP, {}),\n        container,\n      );\n      expect(renderCount).toBe(1);\n\n      render(\n        createComponentVNode(VNodeFlags.ComponentClass, TestCWRP, {\n          foo: 1,\n        }),\n        container,\n      );\n      expect(renderCount).toBe(2);\n      done();\n    });\n  });\n\n  describe('didUpdate and setState', () => {\n    it('order', (done) => {\n      class Test extends Component<{ scrollTop: number }, any> {\n        public state = {\n          testScrollTop: 0,\n        };\n\n        constructor(props, context) {\n          super(props, context);\n        }\n\n        public componentWillReceiveProps(nextProps) {\n          if (nextProps.scrollTop !== 0) {\n            this.setState({ testScrollTop: nextProps.scrollTop });\n          }\n        }\n\n        public componentDidUpdate(_prevProps, prevState) {\n          expect(prevState.testScrollTop).toBe(0);\n          expect(this.state.testScrollTop).toBe(200);\n        }\n\n        public render() {\n          return <div style={{ 'background-attachment': 'scroll' }}>aa</div>;\n        }\n      }\n\n      class Example extends Component<\n        { name: string },\n        { exampleScrollTop: number }\n      > {\n        public state = {\n          exampleScrollTop: 0,\n        };\n\n        constructor(props, context) {\n          super(props, context);\n        }\n\n        public render() {\n          return <Test scrollTop={this.state.exampleScrollTop} />;\n        }\n\n        public componentDidMount() {\n          setTimeout(() => {\n            this.setState({ exampleScrollTop: 200 });\n            rerender();\n\n            done();\n          }, 50);\n        }\n      }\n\n      render(<Example name=\"World\" />, container);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/styles.spec.tsx",
    "content": "import { render } from 'inferno';\nimport { type PropertiesHyphen } from 'csstype';\n\nfunction styleNode(style) {\n  return <div style={style} />;\n}\n\nfunction isCSSvariablesSupported() {\n  const div = document.createElement('div');\n  document.body.appendChild(div);\n  div.style.cssText = '--my-color:red;background-color:var(--my-color);';\n  const backgroundIsRed =\n    getComputedStyle(div).backgroundColor === 'rgb(255, 0, 0)';\n  document.body.removeChild(div);\n\n  return backgroundIsRed;\n}\n\ndescribe('CSS style properties (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should set and remove dynamic styles', () => {\n    const styles = {\n      display: 'none',\n      'font-family': 'Arial',\n      'line-height': 2,\n    };\n\n    render(<div style={styles} />, container);\n    expect(container.firstChild.style.fontFamily).toBe('Arial');\n    expect(container.firstChild.style.lineHeight).toBe('2');\n\n    render(<div />, container);\n    expect(container.firstChild.style.fontFamily).toBe('');\n    expect(container.firstChild.style.lineHeight).toBe('');\n  });\n\n  it('should update styles if initially null', () => {\n    let styles: PropertiesHyphen | null = null;\n    render(<div style={styles} />, container);\n\n    styles = { display: 'block' };\n\n    render(<div style={styles} />, container);\n    expect(container.firstChild.style.display).toBe('block');\n  });\n\n  it('should update styles if updated to null multiple times', () => {\n    let styles: PropertiesHyphen | null = null;\n\n    render(<div style={undefined} />, container);\n\n    render(<div style={styles} />, container);\n    expect(container.firstChild.style.display).toBe('');\n\n    styles = { display: 'block' };\n\n    render(<div style={styles} />, container);\n    expect(container.firstChild.style.display).toBe('block');\n\n    render(<div style={null} />, container);\n    expect(container.firstChild.style.display).toBe('');\n\n    render(<div style={styles} />, container);\n    expect(container.firstChild.style.display).toBe('block');\n\n    render(<div style={null} />, container);\n    expect(container.firstChild.style.display).toBe('');\n  });\n\n  it('should update styles when `style` changes from null to object', () => {\n    const styles = { color: 'red' };\n    // @ts-expect-error\n    render(<div style={123} />, container);\n    render(<div style={styles} />, container);\n    render(<div />, container);\n    render(<div style={styles} />, container);\n\n    const stubStyle = container.firstChild.style;\n    expect(stubStyle.color).toBe('red');\n  });\n\n  it('should support different unit types - em and mm', () => {\n    const styles = { height: '200em', width: '20mm' };\n    render(<div style={styles} />, container);\n    render(<div />, container);\n    render(<div style={styles} />, container);\n\n    const stubStyle = container.firstChild.style;\n    expect(stubStyle.height).toBe('200em');\n    expect(stubStyle.width).toBe('20mm');\n  });\n\n  it('should clear all the styles when removing `style`', () => {\n    const styles = { display: 'none', color: 'red' };\n    render(<div style={styles} />, container);\n\n    const stubStyle = container.firstChild.style;\n    expect(stubStyle.display).toBe('none');\n    expect(stubStyle.color).toBe('red');\n  });\n\n  it('Should change styles', () => {\n    const stylesOne = { color: 'red' };\n    render(styleNode(stylesOne), container);\n    expect(container.firstChild.style.color).toBe('red');\n\n    const styles = { color: 'blue' };\n    render(styleNode(styles), container);\n    expect(container.firstChild.style.color).toBe('blue');\n\n    const stylesTwo = { color: 'orange' };\n    render(styleNode(stylesTwo), container);\n    expect(container.firstChild.style.color).toBe('orange');\n\n    const stylesThree = { color: 'orange' };\n    render(styleNode(stylesThree), container);\n    expect(container.firstChild.style.color).toBe('orange');\n  });\n\n  it('Should remove style attribute when next value is null', () => {\n    const stylesOne = { color: 'green' };\n    render(styleNode(stylesOne), container);\n    expect(container.firstChild.style.color).toBe('green');\n\n    render(styleNode(null), container);\n    expect(container.firstChild.style.cssText).toBe('');\n    // expect(container.innerHTML).to.eql('<div></div>');\n  });\n\n  it('Should remove style attribute when single prop value is undefined', () => {\n    const stylesOne = {\n      'text-align': 'center',\n      color: 'red',\n      display: 'block',\n    };\n    render(styleNode(stylesOne), container);\n    expect(container.firstChild.style.textAlign).toBe('center');\n\n    const stylesTwo = { 'text-align': 'left', display: 'none' };\n    render(styleNode(stylesTwo), container);\n    expect(container.firstChild.style.textAlign).toBe('left');\n    expect(container.firstChild.style.display).toBe('none');\n    expect(container.firstChild.style.color).toBe('');\n  });\n\n  // Test for CSS variable support, depends on browser\n  if (isCSSvariablesSupported()) {\n    it('Should support inline CSS variables string way', () => {\n      render(\n        <div style=\"--my-color:red;background-color:var(--my-color);\" />,\n        container,\n      );\n\n      expect(getComputedStyle(container.firstChild).backgroundColor).toBe(\n        'rgb(255, 0, 0)',\n      ); // verify its red\n    });\n\n    it('Should support inline CSS variables object way', () => {\n      render(\n        <div\n          style={{ '--my-color': 'red', 'background-color': 'var(--my-color)' }}\n        />,\n        container,\n      );\n\n      expect(getComputedStyle(container.firstChild).backgroundColor).toBe(\n        'rgb(255, 0, 0)',\n      ); // verify its red\n    });\n  }\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/svgXlink.spec.tsx",
    "content": "import { render } from 'inferno';\n\ndescribe('createTree - SVG (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n  });\n\n  afterEach(function () {\n    render(null, container);\n  });\n\n  it('should remove namespaced SVG attributes', () => {\n    render(\n      <svg>\n        <image xlink:href=\"http://i.imgur.com/w7GCRPb.png\" />\n      </svg>,\n      container,\n    );\n\n    expect(container.firstChild.tagName).toEqual('svg');\n    expect(\n      container.firstChild.firstChild.hasAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe(true);\n\n    render(\n      <svg>\n        <image />\n      </svg>,\n      container,\n    );\n\n    expect(container.firstChild.tagName).toEqual('svg');\n    expect(\n      container.firstChild.firstChild.hasAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe(false);\n  });\n\n  it('should update namespaced SVG attributes', () => {\n    render(\n      <svg>\n        <image xlink:href=\"http://i.imgur.com/w7GCRPb.png\" />\n      </svg>,\n      container,\n    );\n\n    expect(container.firstChild.tagName).toEqual('svg');\n    expect(\n      container.firstChild.firstChild.hasAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe(true);\n\n    render(\n      <svg>\n        <image xlink:href=\"http://i.imgur.com/JvqCM2p.png\" />\n      </svg>,\n      container,\n    );\n\n    expect(container.firstChild.tagName).toEqual('svg');\n    expect(\n      container.firstChild.firstChild.getAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe('http://i.imgur.com/JvqCM2p.png');\n  });\n\n  it('should add / change / remove xlink:href attribute', () => {\n    render(\n      <svg>\n        <use xlink:href=\"#test\" />\n      </svg>,\n      container,\n    );\n\n    expect(\n      container.firstChild.firstChild.getAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe('#test');\n\n    render(\n      <svg>\n        <use class=\"test\" xlink:href=\"#changed\" />\n      </svg>,\n      container,\n    );\n\n    expect(\n      container.firstChild.firstChild.getAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe('#changed');\n\n    render(\n      <svg>\n        <use />\n      </svg>,\n      container,\n    );\n\n    expect(\n      container.firstChild.firstChild.hasAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe(false);\n  });\n\n  it('should add / change / remove xlinkHref attribute (babel plugin should transpile it)', () => {\n    render(\n      <svg>\n        <use xlinkHref=\"#test\" />\n      </svg>,\n      container,\n    );\n\n    expect(\n      container.firstChild.firstChild.getAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe('#test');\n\n    render(\n      <svg>\n        <use xlinkHref=\"#changed\" />\n      </svg>,\n      container,\n    );\n\n    expect(\n      container.firstChild.firstChild.getAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe('#changed');\n\n    render(\n      <svg>\n        <use />\n      </svg>,\n      container,\n    );\n\n    expect(\n      container.firstChild.firstChild.hasAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/topcontext.spec.tsx",
    "content": "import { Component, createFragment, Fragment, render } from 'inferno';\nimport { ChildFlags } from 'inferno-vnode-flags';\n\ndescribe('top level context', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should be possible to seed context object in render', () => {\n    function Child(_props, context) {\n      return (\n        <span>\n          {context.foo} {context.bar}\n        </span>\n      );\n    }\n\n    render(<Child />, container, null, {\n      bar: 'second',\n      foo: 'first',\n    });\n\n    expect(container.innerHTML).toBe('<span>first second</span>');\n  });\n\n  it('Should merge top level context with child context', () => {\n    function Child(_props, context) {\n      return (\n        <span>\n          {context.foo} {context.bar}\n        </span>\n      );\n    }\n\n    class Parent extends Component<any, any> {\n      public getChildContext() {\n        return {\n          foo: 'bar',\n        };\n      }\n\n      public render(_props, _state, context) {\n        return [<div>{context.foo}</div>, <Child />];\n      }\n    }\n\n    render(<Parent />, container, null, {\n      bar: 'second',\n      foo: 'first',\n    });\n\n    expect(container.innerHTML).toBe('<div>first</div><span>bar second</span>');\n  });\n\n  it('Should pass context correctly through Fragment when it has single child', () => {\n    function Child(_props, context) {\n      return (\n        <span>\n          {context.foo} {context.bar}\n        </span>\n      );\n    }\n\n    class Parent extends Component<any, any> {\n      public render() {\n        return createFragment(<Child />, ChildFlags.HasVNodeChildren);\n      }\n    }\n\n    render(<Parent />, container, null, {\n      bar: 'second',\n      foo: 'first',\n    });\n\n    expect(container.innerHTML).toBe('<span>first second</span>');\n  });\n\n  it('Should pass context correctly through Fragment when it has multiple children', () => {\n    function Child(_props, context) {\n      return (\n        <span>\n          {context.foo} {context.bar}\n        </span>\n      );\n    }\n\n    class Parent extends Component<any, any> {\n      public getChildContext() {\n        return {\n          foo: 'bar',\n        };\n      }\n\n      public render(_props, _state, context) {\n        return [\n          <div>{context.foo}</div>,\n          <Fragment>\n            <Child />\n          </Fragment>,\n        ];\n      }\n    }\n\n    render(\n      <Fragment>\n        <Parent />\n      </Fragment>,\n      container,\n      null,\n      {\n        bar: 'second',\n        foo: 'first',\n      },\n    );\n\n    expect(container.innerHTML).toBe('<div>first</div><span>bar second</span>');\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/transition.spec.tsx",
    "content": "import { render } from 'inferno';\n\ndescribe('transition events', () => {\n  let container;\n\n  function forceReflow() {\n    return document.body.clientHeight;\n  }\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  const transitionStyles = {\n    background: 'red',\n    height: '16px',\n    left: '16px',\n    position: 'absolute' as any,\n    top: '16px',\n    transition: 'left 1ms',\n    width: '16px',\n  };\n\n  it('should call \"ontransitionend\" at the end of a transition', (done) => {\n    render(\n      <div\n        style={transitionStyles}\n        onclick={(e) => {\n          (e.target as HTMLDivElement).style.left = '50px';\n        }}\n        onTransitionEnd={(e) => {\n          expect(e.type).toEqual('transitionend');\n          done();\n        }}\n      />,\n      container,\n    );\n    // Be absolutely sure the transition has been applied through style\n    forceReflow();\n    const div = container.firstChild;\n    div.click();\n    // Be absolutely sure the transition has been applied through style\n    forceReflow();\n  });\n\n  it('should call \"onTransitionEnd\" at the end of a transition', (done) => {\n    render(\n      <div\n        style={transitionStyles}\n        onclick={(e) => {\n          (e.target as HTMLDivElement).style.left = '100px';\n        }}\n        onTransitionEnd={(e) => {\n          expect(e.type).toEqual('transitionend');\n          done();\n        }}\n      />,\n      container,\n    );\n    // Be absolutely sure the transition has been applied through style\n    forceReflow();\n    const div = container.firstChild;\n    div.click();\n    // Be absolutely sure the transition has been applied through style\n    forceReflow();\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/types.children.spec.tsx",
    "content": "import { Component, type InfernoNode, type InfernoSingleNode } from 'inferno';\n\ndescribe('children types', () => {\n  it('Should be possible to type child as component', () => {\n    interface ParentComponentProps {\n      children: FooBarCom;\n    }\n\n    class FooBarCom extends Component<any, any> {\n      constructor(p, c) {\n        super(p, c);\n      }\n\n      public myMethod() {\n        return 'foobar';\n      }\n\n      public render({ children }) {\n        return <div>{children}</div>;\n      }\n    }\n\n    class ParentComponent extends Component<ParentComponentProps, any> {\n      constructor(p, c) {\n        super(p, c);\n      }\n\n      public render({ children }: ParentComponentProps) {\n        children.myMethod();\n        this.props.children.myMethod();\n        return <div>{children}</div>;\n      }\n    }\n\n    // @ts-expect-error\n    const a = <ParentComponent></ParentComponent>;\n\n    const valid = (\n      <ParentComponent>\n        <FooBarCom />\n      </ParentComponent>\n    );\n\n    expect(valid).toBeDefined();\n  });\n\n  it('Should be possible to type child as array', () => {\n    interface ParentComponentProps {\n      children: FooBarCom[];\n    }\n\n    class FooBarCom extends Component<any, any> {\n      constructor(p, c) {\n        super(p, c);\n      }\n\n      public myMethod() {\n        return 'foobar';\n      }\n\n      public render({ children }) {\n        return <div>{children}</div>;\n      }\n    }\n\n    class ParentComponent extends Component<ParentComponentProps, any> {\n      constructor(p, c) {\n        super(p, c);\n      }\n\n      public render({ children }: ParentComponentProps) {\n        children[0].myMethod();\n        this.props.children[0].myMethod();\n        return <div>{children}</div>;\n      }\n    }\n\n    // @ts-expect-error\n    const a = <ParentComponent></ParentComponent>;\n\n    const valid = <ParentComponent>{[<FooBarCom />]}</ParentComponent>;\n    const valid1 = (\n      <ParentComponent>\n        <FooBarCom />\n        <FooBarCom />\n      </ParentComponent>\n    );\n\n    const alsoValidForNow = (\n      <ParentComponent>\n        <FooBarCom />\n      </ParentComponent>\n    );\n\n    expect(valid).toBeDefined();\n    expect(valid1).toBeDefined();\n    expect(alsoValidForNow).toBeDefined();\n  });\n\n  it('Should be possible to type child as InfernoNode', () => {\n    interface ParentComponentProps {\n      children?: InfernoNode;\n    }\n\n    class FooBarCom extends Component<any, any> {\n      constructor(p, c) {\n        super(p, c);\n      }\n\n      public myMethod() {\n        return 'foobar';\n      }\n\n      public render({ children }) {\n        return <div>{children}</div>;\n      }\n    }\n\n    class ParentComponent extends Component<ParentComponentProps, any> {\n      constructor(p, c) {\n        super(p, c);\n      }\n\n      public render({ children }: ParentComponentProps) {\n        // children.myMethod();\n        // this.props.children.myMethod();\n        return <div>{children}</div>;\n      }\n    }\n\n    // InfernoNode accepts any valid JSX as children\n    const valid = (\n      <ParentComponent>\n        <FooBarCom />\n        <FooBarCom />\n      </ParentComponent>\n    );\n\n    // Children defined optional so leaving it empty is also ok\n    const valid2 = <ParentComponent></ParentComponent>;\n\n    // Single child also ok\n    const valid3 = (\n      <ParentComponent>\n        <FooBarCom />\n      </ParentComponent>\n    );\n\n    expect(valid).toBeDefined();\n    expect(valid2).toBeDefined();\n    expect(valid3).toBeDefined();\n  });\n\n  it('Should be possible to type child as InfernoNode', () => {\n    interface ParentComponentProps {\n      children: InfernoSingleNode;\n    }\n\n    class FooBarCom extends Component<any, any> {\n      constructor(p, c) {\n        super(p, c);\n      }\n\n      public myMethod() {\n        return 'foobar';\n      }\n\n      public render({ children }) {\n        return <div>{children}</div>;\n      }\n    }\n\n    class ParentComponent extends Component<ParentComponentProps, any> {\n      constructor(p, c) {\n        super(p, c);\n      }\n\n      public render({ children }: ParentComponentProps) {\n        // children.myMethod();\n        // this.props.children.myMethod();\n        return <div>{children}</div>;\n      }\n    }\n\n    // Children defined InfernoSingleNode so array is not acceptable\n    const invalid1 = (\n      // @ts-expect-error\n      <ParentComponent>\n        <FooBarCom />\n        <FooBarCom />\n      </ParentComponent>\n    );\n\n    // Children not defined optional so leaving it empty is error\n    // @ts-expect-error\n    const invalid2 = <ParentComponent></ParentComponent>;\n\n    // Single child component is ok\n    const valid1 = (\n      <ParentComponent>\n        <FooBarCom />\n      </ParentComponent>\n    );\n\n    // Single child div is ok\n    const valid2 = (\n      <ParentComponent>\n        <div>1</div>\n      </ParentComponent>\n    );\n\n    expect(invalid1).toBeDefined();\n    expect(invalid2).toBeDefined();\n    expect(valid1).toBeDefined();\n    expect(valid2).toBeDefined();\n  });\n\n  it('Should be possible to type child as another component type', () => {\n    class FooBarCom extends Component<any, any> {\n      constructor(p, c) {\n        super(p, c);\n      }\n\n      public myMethod() {\n        return 'foobar';\n      }\n\n      public render({ children }) {\n        return <div>{children}</div>;\n      }\n    }\n\n    interface ParentComponentProps {\n      children: FooBarCom[];\n    }\n\n    class ParentComponent extends Component<ParentComponentProps, any> {\n      public render({ children }: ParentComponentProps) {\n        // children.myMethod();\n        // this.props.children.myMethod();\n        return <div>{children}</div>;\n      }\n    }\n\n    // Children defined InfernoSingleNode so array is not acceptable\n    const invalid1 = (\n      <ParentComponent>\n        <FooBarCom />\n        <FooBarCom />\n      </ParentComponent>\n    );\n\n    // Children not defined optional so leaving it empty is error\n    // @ts-expect-error\n    const invalid2 = <ParentComponent></ParentComponent>;\n\n    // Single child component is ok\n    const valid1 = (\n      <ParentComponent>\n        <FooBarCom />\n      </ParentComponent>\n    );\n\n    // Single child div is ok\n    const valid2 = (\n      <ParentComponent>\n        <div>1</div>\n      </ParentComponent>\n    );\n\n    expect(invalid1).toBeDefined();\n    expect(invalid2).toBeDefined();\n    expect(valid1).toBeDefined();\n    expect(valid2).toBeDefined();\n  });\n\n  it('Should be possible to type child as another component type', () => {\n    class FooBarCom extends Component<any, any> {\n      constructor(p, c) {\n        super(p, c);\n      }\n\n      public myMethod() {\n        return 'foobar';\n      }\n\n      public render({ children }: any) {\n        return <div>{children}</div>;\n      }\n    }\n\n    interface ParentComponentProps {\n      children: FooBarCom;\n    }\n\n    class ParentComponent extends Component<ParentComponentProps, any> {\n      public render({ children }: Readonly<ParentComponentProps>) {\n        children.myMethod();\n        this.props.children.myMethod();\n        return <div>{children}</div>;\n      }\n    }\n\n    // Children defined InfernoSingleNode so array is not acceptable\n    const invalid1 = (\n      // @ts-expect-error\n      <ParentComponent>\n        <FooBarCom />\n        <FooBarCom />\n      </ParentComponent>\n    );\n\n    // Children not defined optional so leaving it empty is error\n    // @ts-expect-error\n    const invalid2 = <ParentComponent></ParentComponent>;\n\n    // Single child component is ok\n    const valid1 = (\n      <ParentComponent>\n        <FooBarCom />\n      </ParentComponent>\n    );\n\n    // Single child div is ok\n    const valid2 = (\n      <ParentComponent>\n        <div>1</div>\n      </ParentComponent>\n    );\n\n    expect(invalid1).toBeDefined();\n    expect(invalid2).toBeDefined();\n    expect(valid1).toBeDefined();\n    expect(valid2).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/types.spec.tsx",
    "content": "import {\n  Component,\n  type ComponentType,\n  createComponentVNode,\n  createRef,\n  createVNode,\n  type InfernoNode,\n  linkEvent,\n  type Ref,\n  render,\n} from 'inferno';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\n\ndescribe('top level context', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('Rendering types', () => {\n    it('Should render SFC jsx node', () => {\n      const MyComponent = (props) => {\n        return <div>{props.children}</div>;\n      };\n\n      render(<MyComponent />, container);\n    });\n\n    it('Should be possible to return string from render SFC', () => {\n      const MyComponent = () => {\n        return 'd';\n      };\n\n      render(<MyComponent />, container);\n    });\n\n    it('Should be possible to return number from render SFC', () => {\n      const MyComponent = () => {\n        return 1;\n      };\n\n      render(<MyComponent />, container);\n    });\n\n    it('Should be possible to return null from render SFC', () => {\n      const MyComponent = () => {\n        return null;\n      };\n\n      render(<MyComponent />, container);\n    });\n\n    describe('class component', function () {\n      it('Should render jsx node - children', () => {\n        class MyComponent extends Component<any, any> {\n          public render(props) {\n            return <div>{props.children}</div>;\n          }\n        }\n\n        render(<MyComponent />, container);\n      });\n\n      it('Should ComponentType to be used as parameter for createComponentVNode', () => {\n        interface TestCompProps {\n          foo: number;\n          children?: InfernoNode;\n        }\n\n        class TestComp extends Component<TestCompProps, any> {\n          public render(props) {\n            return createVNode(\n              VNodeFlags.HtmlElement,\n              'div',\n              null,\n              props.foo,\n              ChildFlags.HasTextChildren,\n            );\n          }\n        }\n\n        function TestFuncComp(props: TestCompProps) {\n          return <span>{props.foo}</span>;\n        }\n\n        function createComponent(val: number): ComponentType<{\n          foo: number;\n        }> {\n          switch (val) {\n            case 0:\n              return TestComp;\n            default:\n              return TestFuncComp;\n          }\n        }\n\n        class MyComponent extends Component<{ val: number }, any> {\n          public render() {\n            return createComponentVNode(\n              VNodeFlags.ComponentUnknown,\n              createComponent(this.props.val),\n              { foo: 765 },\n            );\n          }\n        }\n\n        render(<MyComponent val={1} />, container);\n\n        expect(container.innerHTML).toBe('<span>765</span>');\n\n        render(<MyComponent val={0} />, container);\n\n        expect(container.innerHTML).toBe('<div>765</div>');\n      });\n\n      it('Should render children directly (props)', () => {\n        class MyComponent extends Component<any, any> {\n          public render(props) {\n            return props.children;\n          }\n        }\n\n        render(<MyComponent />, container);\n      });\n\n      it('Should render children directly (this)', () => {\n        class MyComponent extends Component<any, any> {\n          public render() {\n            return this.props.children;\n          }\n        }\n\n        render(<MyComponent />, container);\n      });\n\n      it('Should be possible to return string from class component render', () => {\n        class MyComponent extends Component<any, any> {\n          public render() {\n            return 'd';\n          }\n        }\n\n        render(<MyComponent />, container);\n      });\n\n      it('Should be possible to return number from class component render', () => {\n        class MyComponent extends Component<any, any> {\n          public render() {\n            return 1;\n          }\n        }\n\n        render(<MyComponent />, container);\n      });\n\n      it('Should be possible to return null from class component render', () => {\n        class MyComponent extends Component<any, any> {\n          public render() {\n            return null;\n          }\n        }\n\n        render(<MyComponent />, container);\n      });\n\n      it('Should be possible to return InfernoNode from class component render', () => {\n        class FooBar extends Component<any, any> {\n          public render() {\n            return 'foobar';\n          }\n        }\n\n        class MyComponent extends Component<any, any> {\n          public render() {\n            let Val: InfernoNode = <FooBar />;\n\n            if (this.props.check) {\n              Val = <div>1</div>;\n            } else {\n              Val = <div>{Val}</div>;\n            }\n\n            return Val;\n          }\n        }\n\n        render(<MyComponent />, container);\n      });\n    });\n  });\n\n  describe('JSX', function () {\n    it('Should allow setting events null', function () {\n      render(<div onClick={null} />, container);\n    });\n\n    it('Should allow setting linkEvent as event', function () {\n      const myObj: { a: number } = {\n        a: 1,\n      };\n\n      function myFunction(data, ev) {\n        expect(data.a).toBe(1);\n        expect(ev).toBeDefined();\n      }\n\n      render(<div onClick={linkEvent(myObj, myFunction)} />, container);\n    });\n\n    it('styles object', function () {\n      const getColor = () => 'red';\n\n      render(<div style={{ 'background-color': getColor() }} />, container);\n    });\n\n    it('styles as string', function () {\n      render(<div style=\"background-color: red\" />, container);\n    });\n  });\n\n  describe('ChildFlags', function () {\n    it('Should allow special flags on all elements', function () {\n      const refObj = createRef<HTMLDivElement>();\n      const text = 'foobar';\n      const row = (\n        <div className=\"floating-row-number\" $HasTextChildren>\n          {text}\n        </div>\n      );\n\n      render(\n        <div className=\"floating-row-numbers\" ref={refObj} $HasVNodeChildren>\n          {row}\n        </div>,\n        container,\n      );\n    });\n\n    it('Should allow special flags on SVG', function () {\n      const refObj = createRef<SVGSVGElement>();\n      const text = 'foobar';\n      const row = (\n        <div className=\"floating-row-number\" $HasTextChildren>\n          {text}\n        </div>\n      );\n\n      render(\n        <svg className=\"floating-row-numbers\" ref={refObj} $HasVNodeChildren>\n          {row}\n        </svg>,\n        container,\n      );\n    });\n\n    it('Should allow null for attributes', function () {\n      const row = <div tabIndex={null}></div>;\n      const aria = <div aria-activedescendant={null}></div>;\n\n      expect(row).not.toBeNull();\n      expect(aria).not.toBeNull();\n    });\n\n    it('Should allow null for ref attribute', function () {\n      const obj: {\n        refWrap: Ref<HTMLDivElement> | null;\n      } = {\n        refWrap: null,\n      };\n\n      render(<div ref={obj.refWrap}></div>, container);\n    });\n  });\n\n  it('Should allow setting native events null', function () {\n    render(<div onclick={null} />, container);\n  });\n\n  it('Should allow setting linkEvent as native event handler', function () {\n    const myObj: { a: number } = {\n      a: 1,\n    };\n\n    function myFunction(data, ev) {\n      expect(data.a).toBe(1);\n      expect(ev).toBeDefined();\n    }\n\n    render(<div onclick={linkEvent(myObj, myFunction)} />, container);\n  });\n});\n"
  },
  {
    "path": "packages/inferno/__tests__/validations.spec.tsx",
    "content": "import { createTextVNode, render } from 'inferno';\nimport { ChildFlags } from 'inferno-vnode-flags';\n\ndescribe('Development warnings', () => {\n  let container;\n\n  function constructInfernoError(message: string) {\n    return new Error(`Inferno Error: ${message}`);\n  }\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  // Browsers format error messages a little bit differently so just skip those in tests. As long as messages are ok its fine.\n  if (global?.usingJSDOM) {\n    describe('Warning two duplicate keys', () => {\n      it('Should throw error if two duplicates is found', () => {\n        const errorNode = (\n          <div>\n            <div key=\"1\">2</div>\n            <div key=\"1\">1</div>\n          </div>\n        );\n\n        expect(() => {\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'Encountered two children with same key: {1}. Location: \\n>> <div>\\n>> <div>\\n',\n          ),\n        );\n      });\n\n      it('Should throw error if two duplicate TEXTs is found with same key', () => {\n        const errorNode = (\n          <div>\n            {createTextVNode('foo', 'foo')}\n            {createTextVNode('foo2', 'foo')}\n          </div>\n        );\n\n        expect(() => {\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'Encountered two children with same key: {foo}. Location: \\n>> Text(foo2)\\n>> <div>\\n',\n          ),\n        );\n      });\n\n      it('Should throw error if two duplicates is found (Component)', () => {\n        const FooBar = ({ children }) => children;\n        const Tester = ({ children }) => children;\n        const errorNode = (\n          <div>\n            <FooBar key=\"1\">2</FooBar>\n            <Tester key=\"1\">1</Tester>\n          </div>\n        );\n\n        expect(() => {\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'Encountered two children with same key: {1}. Location: \\n>> <Tester />\\n>> <div>\\n',\n          ),\n        );\n      });\n\n      it('Should print nice stack of invalid key location', () => {\n        // @ts-expect-error unused children\n        const FooBar = ({ children }) => (\n          <span className=\"parentNode\">\n            <div key={'dup'} />\n            <em key={'dup'} />\n          </span>\n        );\n        const errorNode = (\n          <div>\n            <span>\n              <FooBar>\n                <span>1</span>\n              </FooBar>\n            </span>\n          </div>\n        );\n\n        expect(() => {\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'Encountered two children with same key: {dup}. Location: \\n>> <em>\\n>> <span class=\"parentNode\">\\n',\n          ),\n        );\n      });\n    });\n\n    describe('Warning key missing', () => {\n      it('Should throw error if key is missing', () => {\n        expect(() => {\n          const errorNode = (\n            <div $HasKeyedChildren>\n              <div key=\"1\">2</div>\n              <div>1</div>\n            </div>\n          );\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'ChildFlags.HasKeyedChildren expects all children to have keys; missing key at index 1. Location: \\n>> <div>\\n>> <div>\\n',\n          ),\n        );\n      });\n\n      it('Should if there is one that cannot be keyed for example array', () => {\n        expect(() => {\n          const errorNode = (\n            <div $ChildFlag={ChildFlags.HasKeyedChildren}>\n              {createTextVNode('foo', 'foo')}\n              {['1', '2']}\n            </div>\n          );\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'ChildFlags.HasKeyedChildren expects children to be a flat array; found a nested array at index 1. Location: \\n>> Array(1,2)\\n>> <div>\\n',\n          ),\n        );\n      });\n\n      it('Should show only first 3 items if array is really long one', () => {\n        expect(() => {\n          const errorNode = (\n            <div $ChildFlag={ChildFlags.HasKeyedChildren}>\n              {createTextVNode('foo', 'foo')}\n              {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}\n            </div>\n          );\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'ChildFlags.HasKeyedChildren expects children to be a flat array; found a nested array at index 1. Location: \\n>> Array(1,2,3,...)\\n>> <div>\\n',\n          ),\n        );\n      });\n\n      it('Should throw error if two duplicates is found (Component)', () => {\n        const FooBar = ({ children }) => children;\n        const Tester = ({ children }) => children;\n        const errorNode = (\n          <div>\n            <FooBar key=\"1\">2</FooBar>\n            <Tester key=\"1\">1</Tester>\n          </div>\n        );\n\n        expect(() => {\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'Encountered two children with same key: {1}. Location: \\n>> <Tester />\\n>> <div>\\n',\n          ),\n        );\n      });\n\n      it('Should print nice stack of key missing', () => {\n        const FooBar = () => (\n          <span className=\"parentNode\" $HasKeyedChildren>\n            <div key={'dup'} />\n            {2}\n            <em key={'dup'} />\n          </span>\n        );\n\n        const foobar = (\n          // @ts-expect-error Foobar has no children defined\n          <FooBar>\n            <span>1</span>\n          </FooBar>\n        );\n\n        const errorNode = (\n          <div>\n            <span $HasVNodeChildren>{foobar}</span>\n          </div>\n        );\n\n        expect(() => {\n          render(errorNode, container);\n        }).toThrow(\n          'ChildFlags.HasKeyedChildren expects children to be VNodes; found text at index 1.',\n        );\n      });\n    });\n\n    describe('Warning invalid key type', () => {\n      it('Should throw error if child key is not string or number', () => {\n        const errorNode = <div>{createTextVNode('foo', {} as any)}</div>;\n\n        expect(() => {\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'Encountered child vNode where key property is not string or number. Location: \\n>> Text(foo)\\n>> <div>\\n',\n          ),\n        );\n      });\n    });\n\n    describe('Invalid nodes', () => {\n      it('Should throw error if key is missing', () => {\n        expect(() => {\n          const errorNode = (\n            <div $HasKeyedChildren>\n              <div key=\"1\">2</div>\n              {null}\n            </div>\n          );\n          render(errorNode, container);\n        }).toThrow(\n          'ChildFlags.HasKeyedChildren expects children to be VNodes; found invalid child at index 1. Location:',\n        );\n      });\n\n      it('Should if there is one that cannot be keyed for example array', () => {\n        expect(() => {\n          const errorNode = (\n            <div $ChildFlag={ChildFlags.HasNonKeyedChildren}>\n              {createTextVNode('foo', 'foo')}\n              {null}\n            </div>\n          );\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'ChildFlags.HasNonKeyedChildren expects children to be VNodes; found invalid child at index 1. Location: \\n>> InvalidVNode(null)\\n>> <div>\\n',\n          ),\n        );\n      });\n\n      it('Should support long chain of rendered nodes', () => {\n        expect(() => {\n          const errorNode = (\n            <div className=\"p1\">\n              <div id=\"another\">\n                <div data-attr=\"foobar\">\n                  <div $ChildFlag={ChildFlags.HasNonKeyedChildren}>\n                    {createTextVNode('foo', 'foo')}\n                    {null}\n                  </div>\n                </div>\n              </div>\n            </div>\n          );\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'ChildFlags.HasNonKeyedChildren expects children to be VNodes; found invalid child at index 1. Location: \\n>> InvalidVNode(null)\\n>> <div>\\n',\n          ),\n        );\n      });\n    });\n\n    describe('Child flag validations', () => {\n      it('ChildFlags.HasInvalidChildren is not validated', () => {\n        const errorNode = (\n          <div $ChildFlag={ChildFlags.HasInvalidChildren}>\n            <span />\n          </div>\n        );\n        render(errorNode, container);\n      });\n\n      it('ChildFlags.HasTextChildren should throw for TextVNode children', () => {\n        expect(() => {\n          const errorNode = (\n            <div $HasTextChildren>{createTextVNode('foo')}</div>\n          );\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'ChildFlags.HasTextChildren expects children to be a bare string, not a Text VNode. Location: \\n>> Text(foo)\\n>> <div>\\n',\n          ),\n        );\n      });\n\n      it('ChildFlags.HasTextChildren should throw for non-string children', () => {\n        expect(() => {\n          const errorNode = <div $HasTextChildren>{{a: 1}}</div>;\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'ChildFlags.HasTextChildren expects children to be a string. Location: \\n>> Object({\"a\":1})\\n>> <div>\\n',\n          ),\n        );\n      });\n\n      it('ChildFlags.HasTextChildren should accept string children', () => {\n        expect(() => {\n          render(<div $HasTextChildren>{'foo'}</div>, container);\n        }).not.toThrow();\n      });\n\n      it('ChildFlags.HasTextChildren should accept number (text) children', () => {\n        expect(() => {\n          render(<div $HasTextChildren>1</div>, container);\n\n          expect(container.innerHTML).toBe(\"<div>1</div>\")\n        }).not.toThrow();\n      });\n\n      it('ChildFlags.HasTextChildren should accept number (number) children', () => {\n        expect(() => {\n          render(<div $HasTextChildren>{1}</div>, container);\n\n          expect(container.innerHTML).toBe(\"<div>1</div>\")\n        }).not.toThrow();\n      });\n\n      it('ChildFlags.HasVNodeChildren should not throw for TextVNode children', () => {\n        const errorNode = (\n          <div $HasVNodeChildren>{createTextVNode('foo')}</div>\n        );\n        render(errorNode, container);\n      });\n\n      it('ChildFlags.HasVNodeChildren should accept Element VNode children', () => {\n        expect(() => {\n          render(\n            <div $HasVNodeChildren>\n              <span>foo</span>\n            </div>,\n            container,\n          );\n        }).not.toThrow();\n      });\n\n      it('ChildFlags.HasNonKeyedChildren not should throw for keyed children its simply ignored', () => {\n        const children = [<span key=\"a\" />];\n        const errorNode = (\n          <div $ChildFlag={ChildFlags.HasNonKeyedChildren}>\n            {children as any}\n          </div>\n        );\n        render(errorNode, container);\n      });\n\n      it('ChildFlags.HasNonKeyedChildren should throw for holes', () => {\n        // eslint-disable-next-line no-sparse-arrays\n        const children = [<span />, , <span />];\n\n        expect(() => {\n          const errorNode = (\n            <div $ChildFlag={ChildFlags.HasNonKeyedChildren}>\n              {children as any}\n            </div>\n          );\n          render(errorNode, container);\n        }).toThrow(\n          constructInfernoError(\n            'ChildFlags.HasNonKeyedChildren expects children to be a flat array without holes; found a hole at index 1. Location: \\n>> <div>\\n',\n          ),\n        );\n      });\n\n      it('ChildFlags.HasNonKeyedChildren should accept array of non-keyed VNodes', () => {\n        const children = [<span />, <span />];\n\n        expect(() => {\n          render(\n            <div $ChildFlag={ChildFlags.HasNonKeyedChildren}>\n              {children as any}\n            </div>,\n            container,\n          );\n        }).not.toThrow();\n      });\n\n      it('ChildFlags.HasKeyedChildren should accept array of keyed VNodes', () => {\n        const children = [<span key=\"a\" />, <span key=\"b\" />];\n\n        expect(() => {\n          render(\n            <div $ChildFlag={ChildFlags.HasKeyedChildren}>\n              {children as any}\n            </div>,\n            container,\n          );\n        }).not.toThrow();\n      });\n    });\n  }\n\n  describe('Invalid Element children', () => {\n    it('Input cannot have children', () => {\n      expect(() => {\n        render(<input>foobar</input>, container);\n      }).toThrow(constructInfernoError(\"input elements can't have children.\"));\n    });\n\n    it('TextArea elements cannot have children', () => {\n      expect(() => {\n        render(<textarea>foobar</textarea>, container);\n      }).toThrow(\n        constructInfernoError(\"textarea elements can't have children.\"),\n      );\n    });\n\n    it('Media elements cannot have children', () => {\n      expect(() => {\n        render(<media>foobar</media>, container);\n      }).toThrow(constructInfernoError(\"media elements can't have children.\"));\n    });\n\n    it('< BR > elements cannot have children', () => {\n      expect(() => {\n        render(<br>foobar</br>, container);\n      }).toThrow(constructInfernoError(\"br elements can't have children.\"));\n    });\n\n    it('< img > elements cannot have children', () => {\n      expect(() => {\n        render(<img>foobar</img>, container);\n      }).toThrow(constructInfernoError(\"img elements can't have children.\"));\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno/index.mjs",
    "content": "export * from './dist/index.mjs';\n\nif (process.env.NODE_ENV !== 'production') {\n  console.warn(\n    'You are running production build of Inferno in development mode. Use dev:module entry point.',\n  );\n}\n"
  },
  {
    "path": "packages/inferno/package.json",
    "content": "{\n  \"name\": \"inferno\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"An extremely fast, React-like JavaScript library for building modern user interfaces\",\n  \"author\": {\n    \"name\": \"Dominic Gannaway\",\n    \"email\": \"dg@domgan.com\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"funding\": {\n    \"type\": \"opencollective\",\n    \"url\": \"https://opencollective.com/inferno\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"keywords\": [\n    \"inferno\",\n    \"performance\",\n    \"framework\",\n    \"interfaces\",\n    \"user interfaces\",\n    \"html\",\n    \"renderToString\",\n    \"server\",\n    \"dom\",\n    \"browser\",\n    \"rollup\",\n    \"vdom\"\n  ],\n  \"collective\": {\n    \"type\": \"opencollective\",\n    \"url\": \"https://opencollective.com/inferno\",\n    \"logo\": \"https://opencollective.com/inferno/logo.txt\"\n  },\n  \"scripts\": {\n    \"postinstall\": \"opencollective-postinstall\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\",\n      \"inferno-vnode-flags\"\n    ],\n    \"moduleName\": \"Inferno\"\n  },\n  \"files\": [\n    \"index.cjs\",\n    \"index.mjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno\"\n  },\n  \"devDependencies\": {\n    \"inferno-shared\": \"9.0.11\",\n    \"inferno-utils\": \"9.0.11\"\n  },\n  \"dependencies\": {\n    \"csstype\": \"^3.2.3\",\n    \"inferno-vnode-flags\": \"9.0.11\",\n    \"opencollective-postinstall\": \"^2.0.3\"\n  }\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/constants.ts",
    "content": "export const xlinkNS = 'http://www.w3.org/1999/xlink';\nexport const xmlNS = 'http://www.w3.org/XML/1998/namespace';\n\nexport const namespaces: Record<string, string> = {\n  'xlink:actuate': xlinkNS,\n  'xlink:arcrole': xlinkNS,\n  'xlink:href': xlinkNS,\n  'xlink:role': xlinkNS,\n  'xlink:show': xlinkNS,\n  'xlink:title': xlinkNS,\n  'xlink:type': xlinkNS,\n  'xml:base': xmlNS,\n  'xml:lang': xmlNS,\n  'xml:space': xmlNS,\n};\n"
  },
  {
    "path": "packages/inferno/src/DOM/events/attachEvent.ts",
    "content": "import { isFunction } from 'inferno-shared';\n\nexport function attachEvent(dom, eventName, handler): void {\n  const previousKey = `$${eventName}`;\n  const previousArgs = dom[previousKey];\n\n  if (previousArgs) {\n    if (previousArgs[1].wrapped) {\n      return;\n    }\n    dom.removeEventListener(previousArgs[0], previousArgs[1]);\n    dom[previousKey] = null;\n  }\n\n  if (isFunction(handler)) {\n    dom.addEventListener(eventName, handler);\n    dom[previousKey] = [eventName, handler];\n  }\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/events/delegation.ts",
    "content": "import type { LinkedEvent, SemiSyntheticEvent } from './../../core/types';\nimport { isFunction, isNull, isNullOrUndef } from 'inferno-shared';\nimport {\n  isLastValueSameLinkEvent,\n  normalizeEventName,\n} from './../utils/common';\nimport { isLinkEventObject } from './linkEvent';\n\ninterface IEventData {\n  dom: Element;\n}\n\nexport interface DelegateEventTypes {\n  onClick: unknown;\n  onDblClick: unknown;\n  onFocusIn: unknown;\n  onFocusOut: unknown;\n  onKeyDown: unknown;\n  onKeyPress: unknown;\n  onKeyUp: unknown;\n  onMouseDown: unknown;\n  onMouseMove: unknown;\n  onMouseUp: unknown;\n  onTouchEnd: unknown;\n  onTouchMove: unknown;\n  onTouchStart: unknown;\n}\n\nfunction getDelegatedEventObject(v: unknown): DelegateEventTypes {\n  return {\n    onClick: v,\n    onDblClick: v,\n    onFocusIn: v,\n    onFocusOut: v,\n    onKeyDown: v,\n    onKeyPress: v,\n    onKeyUp: v,\n    onMouseDown: v,\n    onMouseMove: v,\n    onMouseUp: v,\n    onTouchEnd: v,\n    onTouchMove: v,\n    onTouchStart: v,\n  };\n}\nconst attachedEventCounts = getDelegatedEventObject(0);\nconst attachedEvents = getDelegatedEventObject(null);\n\nexport const syntheticEvents = getDelegatedEventObject(true);\n\nfunction updateOrAddSyntheticEvent(name: string, dom): DelegateEventTypes {\n  let eventsObject = dom.$EV;\n\n  if (!eventsObject) {\n    eventsObject = dom.$EV = getDelegatedEventObject(null);\n  }\n  if (!eventsObject[name]) {\n    if (++attachedEventCounts[name] === 1) {\n      attachedEvents[name] = attachEventToDocument(name);\n    }\n  }\n\n  return eventsObject;\n}\n\nexport function unmountSyntheticEvent(name: string, dom): void {\n  const eventsObject = dom.$EV;\n\n  if (eventsObject?.[name]) {\n    if (--attachedEventCounts[name] === 0) {\n      document.removeEventListener(\n        normalizeEventName(name),\n        attachedEvents[name],\n      );\n      attachedEvents[name] = null;\n    }\n    eventsObject[name] = null;\n  }\n}\n\nexport function handleSyntheticEvent(\n  name: string,\n  lastEvent: (() => void) | LinkedEvent<any, any> | null | false | true,\n  nextEvent: (() => void) | LinkedEvent<any, any> | null | false | true,\n  dom,\n): void {\n  if (isFunction(nextEvent)) {\n    updateOrAddSyntheticEvent(name, dom)[name] = nextEvent;\n  } else if (isLinkEventObject(nextEvent)) {\n    if (isLastValueSameLinkEvent(lastEvent, nextEvent)) {\n      return;\n    }\n    updateOrAddSyntheticEvent(name, dom)[name] = nextEvent;\n  } else {\n    unmountSyntheticEvent(name, dom);\n  }\n}\n\n// TODO: When browsers fully support event.composedPath we could loop it through instead of using parentNode property\nfunction getTargetNode(event): any {\n  return isFunction(event.composedPath)\n    ? event.composedPath()[0]\n    : event.target;\n}\n\nfunction dispatchEvents(\n  event: SemiSyntheticEvent<any>,\n  isClick: boolean,\n  name: string,\n  eventData: IEventData,\n): void {\n  let dom = getTargetNode(event);\n  do {\n    // Html Nodes can be nested fe: span inside button in that scenario browser does not handle disabled attribute on parent,\n    // because the event listener is on document.body\n    // Don't process clicks on disabled elements\n    if (isClick && dom.disabled) {\n      return;\n    }\n    const eventsObject = dom.$EV;\n\n    if (!isNullOrUndef(eventsObject)) {\n      const currentEvent = eventsObject[name];\n\n      if (currentEvent) {\n        // linkEvent object\n        eventData.dom = dom;\n        if (currentEvent.event) {\n          currentEvent.event(currentEvent.data, event);\n        } else {\n          currentEvent(event);\n        }\n\n        if (event.cancelBubble) {\n          return;\n        }\n      }\n    }\n    dom = dom.parentNode;\n  } while (!isNull(dom));\n}\n\nfunction stopPropagation(): void {\n  this.cancelBubble = true;\n\n  if (!this.immediatePropagationStopped) {\n    this.stopImmediatePropagation();\n  }\n}\n\nfunction isDefaultPrevented(): boolean {\n  return this.defaultPrevented;\n}\n\nfunction isPropagationStopped(): boolean {\n  return this.cancelBubble;\n}\n\nfunction extendEventProperties(event): IEventData {\n  // Event data needs to be an object to save reference to currentTarget getter\n  const eventData: IEventData = {\n    dom: document as any,\n  };\n\n  event.isDefaultPrevented = isDefaultPrevented;\n  event.isPropagationStopped = isPropagationStopped;\n  event.stopPropagation = stopPropagation;\n\n  Object.defineProperty(event, 'currentTarget', {\n    configurable: true,\n    get: function get() {\n      return eventData.dom;\n    },\n  });\n\n  return eventData;\n}\n\nfunction rootEvent(name: string): (event: SemiSyntheticEvent<any>) => void {\n  const isClick = name === 'onClick' || name === 'onDblClick';\n  return function (event: SemiSyntheticEvent<any>) {\n    dispatchEvents(event, isClick, name, extendEventProperties(event));\n  };\n}\n\nfunction attachEventToDocument(\n  name: string,\n): (event: SemiSyntheticEvent<any>) => void {\n  const attachedEvent = rootEvent(name);\n  document.addEventListener(normalizeEventName(name), attachedEvent);\n  return attachedEvent;\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/events/linkEvent.ts",
    "content": "import type { LinkedEvent } from '../../core/types';\nimport { isFunction, isNull } from 'inferno-shared';\n\n/**\n * Links given data to event as first parameter\n * @param {*} data data to be linked, it will be available in function as first parameter\n * @param {Function} callback Function to be called when event occurs\n * @returns {{data: *, event: Function}}\n */\nexport function linkEvent<T, E extends Event>(\n  data: T,\n  callback: (data: T, event: E) => void,\n): LinkedEvent<T, E> | null {\n  if (isFunction(callback)) {\n    return { data, event: callback };\n  }\n  return null; // Return null when event is invalid, to avoid creating unnecessary event handlers\n}\n\n// object.event should always be function, otherwise its badly created object.\nexport function isLinkEventObject(o): o is LinkedEvent<any, any> {\n  return !isNull(o) && typeof o === 'object';\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/mounting.ts",
    "content": "import type { VNode, ContextObject } from '../core/types';\nimport {\n  isFunction,\n  isNull,\n  isNullOrUndef,\n  isString,\n  isStringOrNumber,\n  throwError,\n} from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport {\n  createVoidVNode,\n  directClone,\n  normalizeRoot,\n} from '../core/implementation';\nimport {\n  AnimationQueues,\n  documentCreateElement,\n  EMPTY_OBJ,\n  findDOMFromVNode,\n  insertOrAppend,\n  safeCall1,\n  setTextContent,\n} from './utils/common';\nimport { mountProps } from './props';\nimport {\n  createClassComponentInstance,\n  renderFunctionalComponent,\n} from './utils/componentUtil';\nimport { validateKeys } from '../core/validate';\nimport { mountRef } from '../core/refs';\n\nexport function mount(\n  vNode: VNode,\n  parentDOM: Element | null,\n  context: ContextObject,\n  isSVG: boolean,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const flags = (vNode.flags |= VNodeFlags.InUse);\n\n  if ((flags & VNodeFlags.Element) !== 0) {\n    mountElement(\n      vNode,\n      parentDOM,\n      context,\n      isSVG,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n  } else if ((flags & VNodeFlags.ComponentClass) !== 0) {\n    mountClassComponent(\n      vNode,\n      parentDOM,\n      context,\n      isSVG,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n  } else if (flags & VNodeFlags.ComponentFunction) {\n    mountFunctionalComponent(\n      vNode,\n      parentDOM,\n      context,\n      isSVG,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n  } else if (flags & VNodeFlags.Text) {\n    mountText(vNode, parentDOM, nextNode);\n  } else if (flags & VNodeFlags.Fragment) {\n    mountFragment(\n      vNode,\n      context,\n      parentDOM,\n      isSVG,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n  } else if (flags & VNodeFlags.Portal) {\n    mountPortal(vNode, context, parentDOM, nextNode, lifecycle, animations);\n  } else if (process.env.NODE_ENV !== 'production') {\n    // Development validation, in production we don't need to throw because it crashes anyway\n    if (typeof vNode === 'object') {\n      throwError(\n        `mount() received an object that's not a valid VNode, you should stringify it first, fix createVNode flags or call normalizeChildren. Object: \"${JSON.stringify(\n          vNode,\n        )}\".`,\n      );\n    } else {\n      throwError(\n        `mount() expects a valid VNode, instead it received an object with the type \"${typeof vNode}\".`,\n      );\n    }\n  }\n}\n\nfunction mountPortal(\n  vNode,\n  context,\n  parentDOM: Element | null,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  mount(\n    vNode.children as VNode,\n    vNode.ref,\n    context,\n    false,\n    null,\n    lifecycle,\n    animations,\n  );\n\n  const placeHolderVNode = createVoidVNode();\n\n  mountText(placeHolderVNode, parentDOM, nextNode);\n\n  vNode.dom = placeHolderVNode.dom;\n}\n\nfunction mountFragment(\n  vNode,\n  context,\n  parentDOM: Element | null,\n  isSVG,\n  nextNode,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  let children = vNode.children;\n  let childFlags = vNode.childFlags;\n\n  // When fragment is optimized for multiple children, check if there is no children and change flag to invalid\n  // This is the only normalization always done, to keep optimization flags API same for fragments and regular elements\n  if (childFlags & ChildFlags.MultipleChildren && children.length === 0) {\n    childFlags = vNode.childFlags = ChildFlags.HasVNodeChildren;\n    children = vNode.children = createVoidVNode();\n  }\n\n  if (childFlags === ChildFlags.HasVNodeChildren) {\n    mount(\n      children as VNode,\n      parentDOM,\n      context,\n      isSVG,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n  } else {\n    mountArrayChildren(\n      children,\n      parentDOM,\n      context,\n      isSVG,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n  }\n}\n\nexport function mountText(\n  vNode: VNode,\n  parentDOM: Element | null,\n  nextNode: Element | null,\n): void {\n  const dom = (vNode.dom = document.createTextNode(\n    vNode.children as string,\n  ) as any);\n\n  if (!isNull(parentDOM)) {\n    insertOrAppend(parentDOM, dom, nextNode);\n  }\n}\n\nexport function mountElement(\n  vNode: VNode,\n  parentDOM: Element | null,\n  context: ContextObject,\n  isSVG: boolean,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const flags = vNode.flags;\n  const props = vNode.props;\n  const className = vNode.className;\n  const childFlags = vNode.childFlags;\n  const dom = (vNode.dom = documentCreateElement(\n    vNode.type,\n    (isSVG = isSVG || (flags & VNodeFlags.SvgElement) > 0),\n  ));\n  let children = vNode.children;\n\n  if (!isNullOrUndef(className) && className !== '') {\n    if (isSVG) {\n      dom.setAttribute('class', className);\n    } else {\n      dom.className = className;\n    }\n  }\n\n  if (process.env.NODE_ENV !== 'production') {\n    validateKeys(vNode);\n  }\n\n  if (childFlags === ChildFlags.HasTextChildren) {\n    setTextContent(dom, children as string);\n  } else if (childFlags !== ChildFlags.HasInvalidChildren) {\n    const childrenIsSVG = isSVG && vNode.type !== 'foreignObject';\n\n    if (childFlags === ChildFlags.HasVNodeChildren) {\n      if ((children as VNode).flags & VNodeFlags.InUse) {\n        vNode.children = children = directClone(children as VNode);\n      }\n      mount(\n        children as VNode,\n        dom,\n        context,\n        childrenIsSVG,\n        null,\n        lifecycle,\n        animations,\n      );\n    } else if (\n      childFlags === ChildFlags.HasKeyedChildren ||\n      childFlags === ChildFlags.HasNonKeyedChildren\n    ) {\n      mountArrayChildren(\n        children,\n        dom,\n        context,\n        childrenIsSVG,\n        null,\n        lifecycle,\n        animations,\n      );\n    }\n  }\n\n  if (!isNull(parentDOM)) {\n    insertOrAppend(parentDOM, dom, nextNode);\n  }\n\n  if (!isNull(props)) {\n    mountProps(vNode, flags, props, dom, isSVG, animations);\n  }\n\n  if (process.env.NODE_ENV !== 'production') {\n    if (isString(vNode.ref)) {\n      throwError(\n        'string \"refs\" are not supported in Inferno 1.0. Use callback ref or Inferno.createRef() API instead.',\n      );\n    }\n  }\n  mountRef(vNode.ref, dom, lifecycle);\n}\n\nexport function mountArrayChildren(\n  children,\n  dom: Element | null,\n  context: ContextObject,\n  isSVG: boolean,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  for (let i = 0; i < children.length; ++i) {\n    let child = children[i];\n\n    if (child.flags & VNodeFlags.InUse) {\n      children[i] = child = directClone(child);\n    }\n    mount(child, dom, context, isSVG, nextNode, lifecycle, animations);\n  }\n}\n\nexport function mountClassComponent(\n  vNode: VNode,\n  parentDOM: Element | null,\n  context: ContextObject,\n  isSVG: boolean,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const instance = createClassComponentInstance(\n    vNode,\n    vNode.type,\n    vNode.props || EMPTY_OBJ,\n    context,\n    isSVG,\n    lifecycle,\n  );\n\n  // If we have a componentDidAppear on this component, we shouldn't allow children to animate so we're passing an dummy animations queue\n  let childAnimations = animations;\n\n  if (isFunction(instance.componentDidAppear)) {\n    childAnimations = new AnimationQueues();\n  }\n  mount(\n    instance.$LI,\n    parentDOM,\n    instance.$CX,\n    isSVG,\n    nextNode,\n    lifecycle,\n    childAnimations,\n  );\n  mountClassComponentCallbacks(vNode.ref, instance, lifecycle, animations);\n}\n\nexport function mountFunctionalComponent(\n  vNode: VNode,\n  parentDOM: Element | null,\n  context: ContextObject,\n  isSVG: boolean,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const ref = vNode.ref;\n  // If we have a componentDidAppear on this component, we shouldn't allow children to animate so we're passing an dummy animations queue\n  let childAnimations = animations;\n  if (!isNullOrUndef(ref) && isFunction(ref.onComponentDidAppear)) {\n    childAnimations = new AnimationQueues();\n  }\n\n  mount(\n    (vNode.children = normalizeRoot(renderFunctionalComponent(vNode, context))),\n    parentDOM,\n    context,\n    isSVG,\n    nextNode,\n    lifecycle,\n    childAnimations,\n  );\n  mountFunctionalComponentCallbacks(vNode, lifecycle, animations);\n}\n\nfunction createClassMountCallback(instance) {\n  return () => {\n    instance.componentDidMount();\n  };\n}\n\nfunction addAppearAnimationHookClass(\n  animations: AnimationQueues,\n  instance,\n  dom: Element,\n): void {\n  animations.componentDidAppear.push(() => {\n    instance.componentDidAppear(dom);\n  });\n}\n\nfunction addAppearAnimationHookFunctional(\n  animations: AnimationQueues,\n  ref,\n  dom: Element,\n  props,\n): void {\n  animations.componentDidAppear.push(() => {\n    ref.onComponentDidAppear(dom, props);\n  });\n}\n\nexport function mountClassComponentCallbacks(\n  ref,\n  instance,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  mountRef(ref, instance, lifecycle);\n\n  if (process.env.NODE_ENV !== 'production') {\n    if (isStringOrNumber(ref)) {\n      throwError(\n        'string \"refs\" are not supported in Inferno 1.0. Use callback ref or Inferno.createRef() API instead.',\n      );\n    } else if (\n      !isNullOrUndef(ref) &&\n      typeof ref === 'object' &&\n      ref.current === void 0\n    ) {\n      throwError(\n        'functional component lifecycle events are not supported on ES2015 class components.',\n      );\n    }\n  }\n\n  if (isFunction(instance.componentDidMount)) {\n    lifecycle.push(createClassMountCallback(instance));\n  }\n  if (isFunction(instance.componentDidAppear)) {\n    addAppearAnimationHookClass(animations, instance, instance.$LI.dom);\n  }\n}\n\nfunction createOnMountCallback(ref, vNode) {\n  return () => {\n    ref.onComponentDidMount(\n      findDOMFromVNode(vNode, true),\n      vNode.props || EMPTY_OBJ,\n    );\n  };\n}\n\nexport function mountFunctionalComponentCallbacks(\n  vNode: VNode,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const ref = vNode.ref;\n\n  if (!isNullOrUndef(ref)) {\n    safeCall1(ref.onComponentWillMount, vNode.props || EMPTY_OBJ);\n    if (isFunction(ref.onComponentDidMount)) {\n      lifecycle.push(createOnMountCallback(ref, vNode));\n    }\n    if (isFunction(ref.onComponentDidAppear)) {\n      addAppearAnimationHookFunctional(\n        animations,\n        ref,\n        findDOMFromVNode(vNode, true) as Element,\n        vNode.props,\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/patching.ts",
    "content": "import type { ContextObject, VNode } from '../core/types';\nimport { isFunction, isInvalid, isNull, isNullOrUndef } from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport {\n  createVoidVNode,\n  directClone,\n  normalizeRoot,\n} from '../core/implementation';\nimport type { Component } from './../core/component';\nimport { mount, mountArrayChildren } from './mounting';\nimport {\n  clearDOM,\n  remove,\n  removeAllChildren,\n  unmount,\n  unmountAllChildren,\n} from './unmounting';\nimport {\n  type AnimationQueues,\n  appendChild,\n  callAllMoveAnimationHooks,\n  createDerivedState,\n  EMPTY_OBJ,\n  findDOMFromVNode,\n  moveVNodeDOM,\n  removeChild,\n  removeVNodeDOM,\n  replaceChild,\n  setTextContent,\n} from './utils/common';\nimport {\n  isControlledFormElement,\n  processElement,\n} from './wrappers/processElement';\nimport { patchProp } from './props';\nimport {\n  renderFunctionalComponent,\n  renderNewInput,\n} from './utils/componentUtil';\nimport { validateKeys } from '../core/validate';\nimport { mountRef, unmountRef } from '../core/refs';\n\nfunction replaceWithNewNode(\n  lastVNode,\n  nextVNode,\n  parentDOM: Element,\n  context: ContextObject,\n  isSVG: boolean,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  unmount(lastVNode, animations);\n\n  if ((nextVNode.flags & lastVNode.flags & VNodeFlags.DOMRef) !== 0) {\n    mount(nextVNode, null, context, isSVG, null, lifecycle, animations);\n    // Single DOM operation, when we have dom references available\n    replaceChild(parentDOM, nextVNode.dom, lastVNode.dom);\n  } else {\n    mount(\n      nextVNode,\n      parentDOM,\n      context,\n      isSVG,\n      findDOMFromVNode(lastVNode, true),\n      lifecycle,\n      animations,\n    );\n    removeVNodeDOM(lastVNode, parentDOM, animations);\n  }\n}\n\nexport function patch(\n  lastVNode: VNode,\n  nextVNode: VNode,\n  parentDOM: Element,\n  context: ContextObject,\n  isSVG: boolean,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const nextFlags = (nextVNode.flags |= VNodeFlags.InUse);\n\n  if (\n    lastVNode.flags !== nextFlags ||\n    lastVNode.type !== nextVNode.type ||\n    lastVNode.key !== nextVNode.key ||\n    nextFlags & VNodeFlags.ReCreate\n  ) {\n    if (lastVNode.flags & VNodeFlags.InUse) {\n      replaceWithNewNode(\n        lastVNode,\n        nextVNode,\n        parentDOM,\n        context,\n        isSVG,\n        lifecycle,\n        animations,\n      );\n    } else {\n      // Last vNode is not in use, it has crashed at application level. Just mount nextVNode and ignore last one\n      mount(\n        nextVNode,\n        parentDOM,\n        context,\n        isSVG,\n        nextNode,\n        lifecycle,\n        animations,\n      );\n    }\n  } else if (nextFlags & VNodeFlags.Element) {\n    patchElement(lastVNode, nextVNode, context, isSVG, lifecycle, animations);\n  } else if (nextFlags & VNodeFlags.ComponentClass) {\n    patchClassComponent(\n      lastVNode,\n      nextVNode,\n      parentDOM,\n      context,\n      isSVG,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n  } else if (nextFlags & VNodeFlags.ComponentFunction) {\n    patchFunctionalComponent(\n      lastVNode,\n      nextVNode,\n      parentDOM,\n      context,\n      isSVG,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n  } else if (nextFlags & VNodeFlags.Text) {\n    patchText(lastVNode, nextVNode);\n  } else if (nextFlags & VNodeFlags.Fragment) {\n    patchFragment(\n      lastVNode,\n      nextVNode,\n      parentDOM,\n      context,\n      isSVG,\n      lifecycle,\n      animations,\n    );\n  } else {\n    patchPortal(lastVNode, nextVNode, context, lifecycle, animations);\n  }\n}\n\nexport function patchSingleTextChild(\n  lastChildren,\n  nextChildren,\n  parentDOM: Element,\n): void {\n  if (lastChildren !== nextChildren) {\n    if (lastChildren !== '') {\n      (parentDOM.firstChild as Node).nodeValue = nextChildren;\n    } else {\n      setTextContent(parentDOM, nextChildren);\n    }\n  }\n}\n\nfunction patchContentEditableChildren(dom, nextChildren): void {\n  if (dom.textContent !== nextChildren) {\n    dom.textContent = nextChildren;\n  }\n}\n\nfunction patchFragment(\n  lastVNode: VNode,\n  nextVNode: VNode,\n  parentDOM: Element,\n  context: ContextObject,\n  isSVG: boolean,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const lastChildren = lastVNode.children as VNode[];\n  let nextChildren = nextVNode.children as any;\n  const lastChildFlags = lastVNode.childFlags;\n  let nextChildFlags = nextVNode.childFlags;\n  let nextNode: Element | null = null;\n\n  // When fragment is optimized for multiple children, check if there is no children and change flag to invalid\n  // This is the only normalization always done, to keep optimization flags API same for fragments and regular elements\n  if (\n    nextChildFlags & ChildFlags.MultipleChildren &&\n    nextChildren.length === 0\n  ) {\n    nextChildFlags = nextVNode.childFlags = ChildFlags.HasVNodeChildren;\n    nextChildren = nextVNode.children = createVoidVNode();\n  }\n\n  const nextIsSingle: boolean =\n    (nextChildFlags & ChildFlags.HasVNodeChildren) !== 0;\n\n  if (lastChildFlags & ChildFlags.MultipleChildren) {\n    const lastLen = lastChildren.length;\n\n    // We need to know Fragment's edge node when\n    if (\n      // It uses keyed algorithm\n      (lastChildFlags & ChildFlags.HasKeyedChildren &&\n        nextChildFlags & ChildFlags.HasKeyedChildren) ||\n      // It transforms from many to single\n      nextIsSingle ||\n      // It will append more nodes\n      (!nextIsSingle && (nextChildren as VNode[]).length > lastLen)\n    ) {\n      // When fragment has multiple children there is always at least one vNode\n      nextNode = (findDOMFromVNode(lastChildren[lastLen - 1], false) as Element)\n        .nextSibling as Element | null;\n    }\n  }\n\n  patchChildren(\n    lastChildFlags,\n    nextChildFlags,\n    lastChildren,\n    nextChildren,\n    parentDOM,\n    context,\n    isSVG,\n    nextNode,\n    lastVNode,\n    lifecycle,\n    animations,\n  );\n}\n\nfunction patchPortal(\n  lastVNode: VNode,\n  nextVNode: VNode,\n  context,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const lastContainer = lastVNode.ref as Element;\n  const nextContainer = nextVNode.ref as Element;\n  const nextChildren = nextVNode.children as VNode;\n\n  patchChildren(\n    lastVNode.childFlags,\n    nextVNode.childFlags,\n    lastVNode.children as VNode,\n    nextChildren,\n    lastContainer,\n    context,\n    false,\n    null,\n    lastVNode,\n    lifecycle,\n    animations,\n  );\n\n  nextVNode.dom = lastVNode.dom;\n\n  if (lastContainer !== nextContainer && !isInvalid(nextChildren)) {\n    const node = nextChildren.dom as Element;\n\n    removeChild(lastContainer, node);\n    appendChild(nextContainer, node);\n  }\n}\n\nexport function patchElement(\n  lastVNode: VNode,\n  nextVNode: VNode,\n  context: ContextObject,\n  isSVG: boolean,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const dom = (nextVNode.dom = lastVNode.dom as Element);\n  const lastProps = lastVNode.props;\n  const nextProps = nextVNode.props;\n  const nextFlags = nextVNode.flags;\n  let isFormElement = false;\n  let hasControlledValue = false;\n  let nextPropsOrEmpty;\n\n  isSVG = isSVG || (nextFlags & VNodeFlags.SvgElement) > 0;\n\n  // inlined patchProps  -- starts --\n  if (lastProps !== nextProps) {\n    const lastPropsOrEmpty = lastProps || EMPTY_OBJ;\n    nextPropsOrEmpty = nextProps || EMPTY_OBJ;\n\n    if (nextPropsOrEmpty !== EMPTY_OBJ) {\n      isFormElement = (nextFlags & VNodeFlags.FormElement) > 0;\n      if (isFormElement) {\n        hasControlledValue = isControlledFormElement(nextPropsOrEmpty);\n      }\n\n      for (const prop in nextPropsOrEmpty) {\n        const lastValue = lastPropsOrEmpty[prop];\n        const nextValue = nextPropsOrEmpty[prop];\n        if (lastValue !== nextValue) {\n          patchProp(\n            prop,\n            lastValue,\n            nextValue,\n            dom,\n            isSVG,\n            hasControlledValue,\n            lastVNode,\n            animations,\n          );\n        }\n      }\n    }\n    if (lastPropsOrEmpty !== EMPTY_OBJ) {\n      for (const prop in lastPropsOrEmpty) {\n        if (\n          isNullOrUndef(nextPropsOrEmpty[prop]) &&\n          !isNullOrUndef(lastPropsOrEmpty[prop])\n        ) {\n          patchProp(\n            prop,\n            lastPropsOrEmpty[prop],\n            null,\n            dom,\n            isSVG,\n            hasControlledValue,\n            lastVNode,\n            animations,\n          );\n        }\n      }\n    }\n  }\n  const nextChildren = nextVNode.children;\n  const nextClassName = nextVNode.className;\n\n  // inlined patchProps  -- ends --\n  if (lastVNode.className !== nextClassName) {\n    if (isNullOrUndef(nextClassName)) {\n      dom.removeAttribute('class');\n    } else if (isSVG) {\n      dom.setAttribute('class', nextClassName);\n    } else {\n      dom.className = nextClassName;\n    }\n  }\n\n  if (process.env.NODE_ENV !== 'production') {\n    validateKeys(nextVNode);\n  }\n  if (nextFlags & VNodeFlags.ContentEditable) {\n    patchContentEditableChildren(dom, nextChildren);\n  } else {\n    patchChildren(\n      lastVNode.childFlags,\n      nextVNode.childFlags,\n      lastVNode.children,\n      nextChildren,\n      dom,\n      context,\n      isSVG && nextVNode.type !== 'foreignObject',\n      null,\n      lastVNode,\n      lifecycle,\n      animations,\n    );\n  }\n\n  if (isFormElement) {\n    processElement(\n      nextFlags,\n      nextVNode,\n      dom,\n      nextPropsOrEmpty,\n      false,\n      hasControlledValue,\n    );\n  }\n\n  const nextRef = nextVNode.ref;\n  const lastRef = lastVNode.ref;\n\n  if (lastRef !== nextRef) {\n    unmountRef(lastRef);\n    mountRef(nextRef, dom, lifecycle);\n  }\n}\n\nfunction replaceOneVNodeWithMultipleVNodes(\n  lastChildren,\n  nextChildren,\n  parentDOM,\n  context,\n  isSVG: boolean,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  unmount(lastChildren, animations);\n\n  mountArrayChildren(\n    nextChildren,\n    parentDOM,\n    context,\n    isSVG,\n    findDOMFromVNode(lastChildren, true),\n    lifecycle,\n    animations,\n  );\n\n  removeVNodeDOM(lastChildren, parentDOM, animations);\n}\n\nfunction commonChildrenSwitch(\n  lastChildren,\n  nextChildren,\n  parentDOM: Element,\n  context: ContextObject,\n  isSVG: boolean,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n  parentVNode: VNode,\n  nextChildFlags:\n    | ChildFlags.UnknownChildren\n    | ChildFlags.HasNonKeyedChildren\n    | ChildFlags.HasKeyedChildren\n    | ChildFlags.MultipleChildren,\n  lastChildFlags:\n    | ChildFlags.UnknownChildren\n    | ChildFlags.HasNonKeyedChildren\n    | ChildFlags.HasKeyedChildren\n    | ChildFlags.MultipleChildren,\n): void {\n  const lastLength = lastChildren.length | 0;\n  const nextLength = nextChildren.length | 0;\n\n  // Fast path's for both algorithms\n  if (lastLength === 0) {\n    if (nextLength > 0) {\n      mountArrayChildren(\n        nextChildren,\n        parentDOM,\n        context,\n        isSVG,\n        nextNode,\n        lifecycle,\n        animations,\n      );\n    }\n  } else if (nextLength === 0) {\n    removeAllChildren(parentDOM, parentVNode, lastChildren, animations);\n  } else if (\n    nextChildFlags === ChildFlags.HasKeyedChildren &&\n    lastChildFlags === ChildFlags.HasKeyedChildren\n  ) {\n    patchKeyedChildren(\n      lastChildren,\n      nextChildren,\n      parentDOM,\n      context,\n      isSVG,\n      lastLength,\n      nextLength,\n      nextNode,\n      parentVNode,\n      lifecycle,\n      animations,\n    );\n  } else {\n    patchNonKeyedChildren(\n      lastChildren,\n      nextChildren,\n      parentDOM,\n      context,\n      isSVG,\n      lastLength,\n      nextLength,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n  }\n}\n\nfunction patchChildren(\n  lastChildFlags: ChildFlags,\n  nextChildFlags: ChildFlags,\n  lastChildren,\n  nextChildren,\n  parentDOM: Element,\n  context: ContextObject,\n  isSVG: boolean,\n  nextNode: Element | null,\n  parentVNode: VNode,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  switch (lastChildFlags) {\n    case ChildFlags.HasVNodeChildren:\n      switch (nextChildFlags) {\n        case ChildFlags.HasVNodeChildren:\n          patch(\n            lastChildren,\n            nextChildren,\n            parentDOM,\n            context,\n            isSVG,\n            nextNode,\n            lifecycle,\n            animations,\n          );\n          break;\n        case ChildFlags.HasInvalidChildren:\n          remove(lastChildren, parentDOM, animations);\n          break;\n        case ChildFlags.HasTextChildren:\n          unmount(lastChildren, animations);\n          setTextContent(parentDOM, nextChildren);\n          break;\n        default:\n          replaceOneVNodeWithMultipleVNodes(\n            lastChildren,\n            nextChildren,\n            parentDOM,\n            context,\n            isSVG,\n            lifecycle,\n            animations,\n          );\n          break;\n      }\n      break;\n    case ChildFlags.HasInvalidChildren:\n      switch (nextChildFlags) {\n        case ChildFlags.HasVNodeChildren:\n          mount(\n            nextChildren,\n            parentDOM,\n            context,\n            isSVG,\n            nextNode,\n            lifecycle,\n            animations,\n          );\n          break;\n        case ChildFlags.HasInvalidChildren:\n          break;\n        case ChildFlags.HasTextChildren:\n          setTextContent(parentDOM, nextChildren);\n          break;\n        default:\n          mountArrayChildren(\n            nextChildren,\n            parentDOM,\n            context,\n            isSVG,\n            nextNode,\n            lifecycle,\n            animations,\n          );\n          break;\n      }\n      break;\n    case ChildFlags.HasTextChildren:\n      switch (nextChildFlags) {\n        case ChildFlags.HasTextChildren:\n          patchSingleTextChild(lastChildren, nextChildren, parentDOM);\n          break;\n        case ChildFlags.HasVNodeChildren:\n          clearDOM(parentDOM, lastChildren, animations);\n          mount(\n            nextChildren,\n            parentDOM,\n            context,\n            isSVG,\n            nextNode,\n            lifecycle,\n            animations,\n          );\n          break;\n        case ChildFlags.HasInvalidChildren:\n          clearDOM(parentDOM, lastChildren, animations);\n          break;\n        default:\n          clearDOM(parentDOM, lastChildren, animations);\n          mountArrayChildren(\n            nextChildren,\n            parentDOM,\n            context,\n            isSVG,\n            nextNode,\n            lifecycle,\n            animations,\n          );\n          break;\n      }\n      break;\n    default:\n      switch (nextChildFlags) {\n        case ChildFlags.HasTextChildren:\n          unmountAllChildren(lastChildren, animations);\n          setTextContent(parentDOM, nextChildren);\n          break;\n        case ChildFlags.HasVNodeChildren:\n          removeAllChildren(parentDOM, parentVNode, lastChildren, animations);\n          mount(\n            nextChildren,\n            parentDOM,\n            context,\n            isSVG,\n            nextNode,\n            lifecycle,\n            animations,\n          );\n          break;\n        case ChildFlags.HasInvalidChildren:\n          removeAllChildren(parentDOM, parentVNode, lastChildren, animations);\n          break;\n        default:\n          commonChildrenSwitch(\n            lastChildren,\n            nextChildren,\n            parentDOM,\n            context,\n            isSVG,\n            nextNode,\n            lifecycle,\n            animations,\n            parentVNode,\n            nextChildFlags,\n            lastChildFlags,\n          );\n          break;\n      }\n      break;\n  }\n}\n\nfunction createDidUpdate(\n  instance: Component<any, any>,\n  lastProps,\n  lastState,\n  snapshot,\n  lifecycle: Array<() => void>,\n): void {\n  lifecycle.push(() => {\n    instance.componentDidUpdate!(lastProps, lastState, snapshot);\n  });\n}\n\nexport function updateClassComponent(\n  instance,\n  nextState,\n  nextProps,\n  parentDOM: Element,\n  context,\n  isSVG: boolean,\n  force: boolean,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const lastState = instance.state;\n  const lastProps = instance.props;\n  const usesNewAPI = Boolean(instance.$N);\n  const hasSCU = isFunction(instance.shouldComponentUpdate);\n\n  if (usesNewAPI) {\n    nextState = createDerivedState(\n      instance,\n      nextProps,\n      nextState !== lastState ? { ...lastState, ...nextState } : nextState,\n    );\n  }\n\n  if (\n    force ||\n    !hasSCU ||\n    (hasSCU && instance.shouldComponentUpdate(nextProps, nextState, context))\n  ) {\n    if (!usesNewAPI && isFunction(instance.componentWillUpdate)) {\n      instance.componentWillUpdate(nextProps, nextState, context);\n    }\n\n    instance.props = nextProps;\n    instance.state = nextState;\n    instance.context = context;\n    let snapshot = null;\n    const nextInput = renderNewInput(instance, nextProps, context);\n\n    if (usesNewAPI && isFunction(instance.getSnapshotBeforeUpdate)) {\n      snapshot = instance.getSnapshotBeforeUpdate(lastProps, lastState);\n    }\n\n    patch(\n      instance.$LI,\n      nextInput,\n      parentDOM,\n      instance.$CX,\n      isSVG,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n\n    // Don't update Last input, until patch has been successfully executed\n    instance.$LI = nextInput;\n\n    if (isFunction(instance.componentDidUpdate)) {\n      createDidUpdate(instance, lastProps, lastState, snapshot, lifecycle);\n    }\n  } else {\n    instance.props = nextProps;\n    instance.state = nextState;\n    instance.context = context;\n  }\n}\n\nfunction patchClassComponent(\n  lastVNode,\n  nextVNode,\n  parentDOM,\n  context,\n  isSVG: boolean,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const instance = (nextVNode.children = lastVNode.children);\n  // If Component has crashed, ignore it to stay functional\n  if (isNull(instance)) {\n    return;\n  }\n\n  instance.$L = lifecycle;\n  const nextProps = nextVNode.props || EMPTY_OBJ;\n  const nextRef = nextVNode.ref;\n  const lastRef = lastVNode.ref;\n  let nextState = instance.state;\n\n  if (!instance.$N) {\n    if (isFunction(instance.componentWillReceiveProps)) {\n      instance.$BR = true;\n      instance.componentWillReceiveProps(nextProps, context);\n      // If instance component was removed during its own update do nothing.\n      if (instance.$UN) {\n        return;\n      }\n      instance.$BR = false;\n    }\n    if (!isNull(instance.$PS)) {\n      nextState = { ...nextState, ...instance.$PS };\n      instance.$PS = null;\n    }\n  }\n\n  updateClassComponent(\n    instance,\n    nextState,\n    nextProps,\n    parentDOM,\n    context,\n    isSVG,\n    false,\n    nextNode,\n    lifecycle,\n    animations,\n  );\n\n  if (lastRef !== nextRef) {\n    unmountRef(lastRef);\n    mountRef(nextRef, instance, lifecycle);\n  }\n}\n\nfunction patchFunctionalComponent(\n  lastVNode,\n  nextVNode,\n  parentDOM,\n  context,\n  isSVG: boolean,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  let shouldUpdate: boolean = true;\n  const nextProps = nextVNode.props || EMPTY_OBJ;\n  const nextRef = nextVNode.ref;\n  const lastProps = lastVNode.props;\n  const nextHooksDefined = !isNullOrUndef(nextRef);\n  const lastInput = lastVNode.children;\n\n  if (nextHooksDefined && isFunction(nextRef.onComponentShouldUpdate)) {\n    shouldUpdate = nextRef.onComponentShouldUpdate(lastProps, nextProps);\n  }\n\n  if (shouldUpdate) {\n    if (nextHooksDefined && isFunction(nextRef.onComponentWillUpdate)) {\n      nextRef.onComponentWillUpdate(lastProps, nextProps);\n    }\n    const nextInput = normalizeRoot(\n      renderFunctionalComponent(nextVNode, context),\n    );\n\n    patch(\n      lastInput,\n      nextInput,\n      parentDOM,\n      context,\n      isSVG,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n    nextVNode.children = nextInput;\n    if (nextHooksDefined && isFunction(nextRef.onComponentDidUpdate)) {\n      nextRef.onComponentDidUpdate(lastProps, nextProps);\n    }\n  } else {\n    nextVNode.children = lastInput;\n  }\n}\n\nfunction patchText(lastVNode: VNode, nextVNode: VNode): void {\n  const nextText = nextVNode.children as string;\n  const dom = (nextVNode.dom = lastVNode.dom);\n\n  if (nextText !== lastVNode.children) {\n    (dom as Element).nodeValue = nextText;\n  }\n}\n\nfunction patchNonKeyedChildren(\n  lastChildren,\n  nextChildren,\n  dom,\n  context: ContextObject,\n  isSVG: boolean,\n  lastChildrenLength: number,\n  nextChildrenLength: number,\n  nextNode: Element | null,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const commonLength =\n    lastChildrenLength > nextChildrenLength\n      ? nextChildrenLength\n      : lastChildrenLength;\n  let i = 0;\n  let nextChild;\n  let lastChild;\n\n  for (; i < commonLength; ++i) {\n    nextChild = nextChildren[i];\n    lastChild = lastChildren[i];\n\n    if (nextChild.flags & VNodeFlags.InUse) {\n      nextChild = nextChildren[i] = directClone(nextChild);\n    }\n\n    patch(\n      lastChild,\n      nextChild,\n      dom,\n      context,\n      isSVG,\n      nextNode,\n      lifecycle,\n      animations,\n    );\n    lastChildren[i] = nextChild;\n  }\n  if (lastChildrenLength < nextChildrenLength) {\n    for (i = commonLength; i < nextChildrenLength; ++i) {\n      nextChild = nextChildren[i];\n\n      if (nextChild.flags & VNodeFlags.InUse) {\n        nextChild = nextChildren[i] = directClone(nextChild);\n      }\n      mount(nextChild, dom, context, isSVG, nextNode, lifecycle, animations);\n    }\n  } else if (lastChildrenLength > nextChildrenLength) {\n    for (i = commonLength; i < lastChildrenLength; ++i) {\n      remove(lastChildren[i], dom, animations);\n    }\n  }\n}\n\nfunction patchKeyedChildren(\n  a: VNode[],\n  b: VNode[],\n  dom,\n  context,\n  isSVG: boolean,\n  aLength: number,\n  bLength: number,\n  outerEdge: Element | null,\n  parentVNode: VNode,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  let aEnd = aLength - 1;\n  let bEnd = bLength - 1;\n  let j: number = 0;\n  let aNode: VNode = a[j];\n  let bNode: VNode = b[j];\n  let nextPos: number;\n  let nextNode;\n\n  // Step 1\n  outer: {\n    // Sync nodes with the same key at the beginning.\n    while (aNode.key === bNode.key) {\n      if (bNode.flags & VNodeFlags.InUse) {\n        b[j] = bNode = directClone(bNode);\n      }\n      patch(\n        aNode,\n        bNode,\n        dom,\n        context,\n        isSVG,\n        outerEdge,\n        lifecycle,\n        animations,\n      );\n      a[j] = bNode;\n      ++j;\n      if (j > aEnd || j > bEnd) {\n        break outer;\n      }\n      aNode = a[j];\n      bNode = b[j];\n    }\n\n    aNode = a[aEnd];\n    bNode = b[bEnd];\n\n    // Sync nodes with the same key at the end.\n    while (aNode.key === bNode.key) {\n      if (bNode.flags & VNodeFlags.InUse) {\n        b[bEnd] = bNode = directClone(bNode);\n      }\n      patch(\n        aNode,\n        bNode,\n        dom,\n        context,\n        isSVG,\n        outerEdge,\n        lifecycle,\n        animations,\n      );\n      a[aEnd] = bNode;\n      aEnd--;\n      bEnd--;\n      if (j > aEnd || j > bEnd) {\n        break outer;\n      }\n      aNode = a[aEnd];\n      bNode = b[bEnd];\n    }\n  }\n\n  if (j > aEnd) {\n    if (j <= bEnd) {\n      nextPos = bEnd + 1;\n      nextNode =\n        nextPos < bLength ? findDOMFromVNode(b[nextPos], true) : outerEdge;\n\n      while (j <= bEnd) {\n        bNode = b[j];\n        if (bNode.flags & VNodeFlags.InUse) {\n          b[j] = bNode = directClone(bNode);\n        }\n        ++j;\n        mount(bNode, dom, context, isSVG, nextNode, lifecycle, animations);\n      }\n    }\n  } else if (j > bEnd) {\n    while (j <= aEnd) {\n      remove(a[j++], dom, animations);\n    }\n  } else {\n    patchKeyedChildrenComplex(\n      a,\n      b,\n      context,\n      aLength,\n      bLength,\n      aEnd,\n      bEnd,\n      j,\n      dom,\n      isSVG,\n      outerEdge,\n      parentVNode,\n      lifecycle,\n      animations,\n    );\n  }\n}\n\nfunction patchKeyedChildrenComplex(\n  a: VNode[],\n  b: VNode[],\n  context,\n  aLength: number,\n  bLength: number,\n  aEnd: number,\n  bEnd: number,\n  j: number,\n  dom: Element,\n  isSVG: boolean,\n  outerEdge: Element | null,\n  parentVNode: VNode,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  let aNode: VNode;\n  let bNode: VNode;\n  // eslint-disable-next-line no-useless-assignment\n  let nextPos: number = 0;\n  // eslint-disable-next-line no-useless-assignment\n  let i: number = 0;\n  let aStart: number = j;\n  const bStart: number = j;\n  const aLeft: number = aEnd - j + 1;\n  const bLeft: number = bEnd - j + 1;\n  const sources = new Int32Array(bLeft + 1);\n  // Keep track if it is possible to remove whole DOM using textContent = '';\n  let canRemoveWholeContent: boolean = aLeft === aLength;\n  let moved: boolean = false;\n  let pos: number = 0;\n  let patched: number = 0;\n\n  // When sizes are small, just loop them through\n  if (bLength < 4 || (aLeft | bLeft) < 32) {\n    for (i = aStart; i <= aEnd; ++i) {\n      aNode = a[i];\n      if (patched < bLeft) {\n        for (j = bStart; j <= bEnd; j++) {\n          bNode = b[j];\n          if (aNode.key === bNode.key) {\n            sources[j - bStart] = i + 1;\n            if (canRemoveWholeContent) {\n              canRemoveWholeContent = false;\n              while (aStart < i) {\n                remove(a[aStart++], dom, animations);\n              }\n            }\n            if (pos > j) {\n              moved = true;\n            } else {\n              pos = j;\n            }\n            if (bNode.flags & VNodeFlags.InUse) {\n              b[j] = bNode = directClone(bNode);\n            }\n            patch(\n              aNode,\n              bNode,\n              dom,\n              context,\n              isSVG,\n              outerEdge,\n              lifecycle,\n              animations,\n            );\n            ++patched;\n            break;\n          }\n        }\n        if (!canRemoveWholeContent && j > bEnd) {\n          remove(aNode, dom, animations);\n        }\n      } else if (!canRemoveWholeContent) {\n        remove(aNode, dom, animations);\n      }\n    }\n  } else {\n    const keyIndex: Record<string, number> = {};\n\n    // Map keys by their index\n    for (i = bStart; i <= bEnd; ++i) {\n      keyIndex[b[i].key as string | number] = i;\n    }\n\n    // Try to patch same keys\n    for (i = aStart; i <= aEnd; ++i) {\n      aNode = a[i];\n\n      if (patched < bLeft) {\n        j = keyIndex[aNode.key as string | number];\n\n        if (j !== void 0) {\n          if (canRemoveWholeContent) {\n            canRemoveWholeContent = false;\n            while (i > aStart) {\n              remove(a[aStart++], dom, animations);\n            }\n          }\n          sources[j - bStart] = i + 1;\n          if (pos > j) {\n            moved = true;\n          } else {\n            pos = j;\n          }\n          bNode = b[j];\n          if (bNode.flags & VNodeFlags.InUse) {\n            b[j] = bNode = directClone(bNode);\n          }\n          patch(\n            aNode,\n            bNode,\n            dom,\n            context,\n            isSVG,\n            outerEdge,\n            lifecycle,\n            animations,\n          );\n          ++patched;\n        } else if (!canRemoveWholeContent) {\n          remove(aNode, dom, animations);\n        }\n      } else if (!canRemoveWholeContent) {\n        remove(aNode, dom, animations);\n      }\n    }\n  }\n  // fast-path: if nothing patched remove all old and add all new\n  if (canRemoveWholeContent) {\n    removeAllChildren(dom, parentVNode, a, animations);\n    mountArrayChildren(\n      b,\n      dom,\n      context,\n      isSVG,\n      outerEdge,\n      lifecycle,\n      animations,\n    );\n  } else if (moved) {\n    const seq = lisAlgorithm(sources);\n    j = seq.length - 1;\n    for (i = bLeft - 1; i >= 0; i--) {\n      if (sources[i] === 0) {\n        pos = i + bStart;\n        bNode = b[pos];\n        if (bNode.flags & VNodeFlags.InUse) {\n          b[pos] = bNode = directClone(bNode);\n        }\n        nextPos = pos + 1;\n        mount(\n          bNode,\n          dom,\n          context,\n          isSVG,\n          nextPos < bLength ? findDOMFromVNode(b[nextPos], true) : outerEdge,\n          lifecycle,\n          animations,\n        );\n      } else if (j < 0 || i !== seq[j]) {\n        pos = i + bStart;\n        bNode = b[pos];\n        nextPos = pos + 1;\n\n        // --- the DOM-node is moved by a call to insertAppend\n        moveVNodeDOM(\n          parentVNode,\n          bNode,\n          dom,\n          nextPos < bLength ? findDOMFromVNode(b[nextPos], true) : outerEdge,\n          animations,\n        );\n      } else {\n        j--;\n      }\n    }\n    // Invoke move animations when all moves have been calculated\n    if (animations.componentWillMove.length > 0) {\n      callAllMoveAnimationHooks(animations.componentWillMove);\n    }\n  } else if (patched !== bLeft) {\n    // when patched count doesn't match b length we need to insert those new ones\n    // loop backwards so we can use insertBefore\n    for (i = bLeft - 1; i >= 0; i--) {\n      if (sources[i] === 0) {\n        pos = i + bStart;\n        bNode = b[pos];\n        if (bNode.flags & VNodeFlags.InUse) {\n          b[pos] = bNode = directClone(bNode);\n        }\n        nextPos = pos + 1;\n        mount(\n          bNode,\n          dom,\n          context,\n          isSVG,\n          nextPos < bLength ? findDOMFromVNode(b[nextPos], true) : outerEdge,\n          lifecycle,\n          animations,\n        );\n      }\n    }\n  }\n}\n\nlet result: Int32Array;\nlet p: Int32Array;\nlet maxLen = 0;\n// https://en.wikipedia.org/wiki/Longest_increasing_subsequence\n\nfunction lisAlgorithm(arr: Int32Array): Int32Array {\n  // Assigning number here tells JIT that these variables are numbers\n  /* eslint-disable no-useless-assignment */\n  let arrI = 0;\n  let i = 0;\n  let j = 0;\n  let k = 0;\n  let u = 0;\n  let v = 0;\n  let c = 0;\n  const len = arr.length;\n  /* eslint-enable no-useless-assignment */\n\n  if (len > maxLen) {\n    maxLen = len;\n    result = new Int32Array(len);\n    p = new Int32Array(len);\n  }\n\n  for (; i < len; ++i) {\n    arrI = arr[i];\n\n    if (arrI !== 0) {\n      j = result[k];\n      if (arr[j] < arrI) {\n        p[i] = j;\n        result[++k] = i;\n        continue;\n      }\n\n      u = 0;\n      v = k;\n\n      while (u < v) {\n        c = (u + v) >> 1;\n        if (arr[result[c]] < arrI) {\n          u = c + 1;\n        } else {\n          v = c;\n        }\n      }\n\n      if (arrI < arr[result[u]]) {\n        if (u > 0) {\n          p[i] = result[u - 1];\n        }\n        result[u] = i;\n      }\n    }\n  }\n\n  u = k + 1;\n  const seq = new Int32Array(u);\n  v = result[u - 1];\n\n  while (u-- > 0) {\n    seq[u] = v;\n    v = p[v];\n    result[u] = 0;\n  }\n\n  return seq;\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/props.ts",
    "content": "import type { VNode } from '../core/types';\nimport { namespaces } from './constants';\nimport { isNull, isNullOrUndef, isString, warning } from 'inferno-shared';\nimport { handleSyntheticEvent, syntheticEvents } from './events/delegation';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport { isSameInnerHTML } from './utils/innerHTML';\nimport {\n  type AnimationQueues,\n  isLastValueSameLinkEvent,\n  normalizeEventName,\n} from './utils/common';\nimport {\n  addFormElementEventHandlers,\n  isControlledFormElement,\n  processElement,\n} from './wrappers/processElement';\nimport { unmount, unmountAllChildren } from './unmounting';\nimport { attachEvent } from './events/attachEvent';\nimport { isLinkEventObject } from './events/linkEvent';\n\nfunction wrapLinkEvent(nextValue): (e) => void {\n  // This variable makes sure there is no \"this\" context in callback\n  const ev = nextValue.event;\n\n  return function (e): void {\n    ev(nextValue.data, e);\n  };\n}\n\nexport function patchEvent(name: string, lastValue, nextValue, dom): void {\n  if (isLinkEventObject(nextValue)) {\n    if (isLastValueSameLinkEvent(lastValue, nextValue)) {\n      return;\n    }\n    nextValue = wrapLinkEvent(nextValue);\n  }\n  attachEvent(dom, normalizeEventName(name), nextValue);\n}\n\n// We are assuming here that we come from patchProp routine\n// -nextAttrValue cannot be null or undefined\nfunction patchStyle(lastAttrValue, nextAttrValue, dom): void {\n  if (isNullOrUndef(nextAttrValue)) {\n    dom.removeAttribute('style');\n    return;\n  }\n  const domStyle = dom.style;\n  let style;\n  let value;\n  if (isString(nextAttrValue)) {\n    domStyle.cssText = nextAttrValue;\n    return;\n  }\n\n  if (!isNullOrUndef(lastAttrValue) && !isString(lastAttrValue)) {\n    for (style in nextAttrValue) {\n      // do not add a hasOwnProperty check here, it affects performance\n      value = nextAttrValue[style];\n      if (value !== lastAttrValue[style]) {\n        domStyle.setProperty(style, value);\n      }\n    }\n\n    for (style in lastAttrValue) {\n      if (isNullOrUndef(nextAttrValue[style])) {\n        domStyle.removeProperty(style);\n      }\n    }\n  } else {\n    for (style in nextAttrValue) {\n      value = nextAttrValue[style];\n      domStyle.setProperty(style, value);\n    }\n  }\n}\n\nfunction patchDangerInnerHTML(\n  lastValue,\n  nextValue,\n  lastVNode,\n  dom,\n  animations: AnimationQueues,\n): void {\n  const lastHtml = lastValue?.__html || '';\n  const nextHtml = nextValue?.__html || '';\n\n  if (lastHtml !== nextHtml) {\n    if (!isNullOrUndef(nextHtml) && !isSameInnerHTML(dom, nextHtml)) {\n      if (!isNull(lastVNode)) {\n        if (lastVNode.childFlags & ChildFlags.MultipleChildren) {\n          unmountAllChildren(lastVNode.children as VNode[], animations);\n        } else if (lastVNode.childFlags === ChildFlags.HasVNodeChildren) {\n          unmount(lastVNode.children, animations);\n        }\n        lastVNode.children = null;\n        lastVNode.childFlags = ChildFlags.HasInvalidChildren;\n      }\n      dom.innerHTML = nextHtml;\n    }\n  }\n}\n\nfunction patchDomProp(nextValue: unknown, dom: Element, prop: string): void {\n  const value = isNullOrUndef(nextValue) ? '' : nextValue;\n  if (dom[prop] !== value) {\n    dom[prop] = value;\n  }\n}\n\nexport function patchProp(\n  prop: string,\n  lastValue: any,\n  nextValue: any,\n  dom: Element,\n  isSVG: boolean,\n  hasControlledValue: boolean,\n  lastVNode: VNode | null,\n  animations: AnimationQueues,\n): void {\n  switch (prop) {\n    case 'children':\n    case 'childrenType':\n    case 'className':\n    case 'defaultValue':\n    case 'key':\n    case 'multiple':\n    case 'ref':\n    case 'selectedIndex':\n      break;\n    case 'autoFocus':\n      (dom as any).autofocus = !!nextValue;\n      break;\n    case 'allowfullscreen':\n    case 'autoplay':\n    case 'capture':\n    case 'checked':\n    case 'controls':\n    case 'default':\n    case 'disabled':\n    case 'hidden':\n    case 'indeterminate':\n    case 'loop':\n    case 'muted':\n    case 'novalidate':\n    case 'open':\n    case 'readOnly':\n    case 'required':\n    case 'reversed':\n    case 'scoped':\n    case 'seamless':\n    case 'selected':\n      dom[prop] = !!nextValue;\n      break;\n    case 'defaultChecked':\n    case 'value':\n    case 'volume':\n      if (hasControlledValue && prop === 'value') {\n        break;\n      }\n      patchDomProp(nextValue, dom, prop);\n      break;\n    case 'style':\n      patchStyle(lastValue, nextValue, dom);\n      break;\n    case 'dangerouslySetInnerHTML':\n      patchDangerInnerHTML(lastValue, nextValue, lastVNode, dom, animations);\n      break;\n    default:\n      if (syntheticEvents[prop]) {\n        handleSyntheticEvent(prop, lastValue, nextValue, dom);\n      } else if (prop.charCodeAt(0) === 111 && prop.charCodeAt(1) === 110) {\n        patchEvent(prop, lastValue, nextValue, dom);\n      } else if (isNullOrUndef(nextValue)) {\n        dom.removeAttribute(prop);\n      } else if (isSVG && namespaces[prop]) {\n        // We optimize for isSVG being false\n        // If we end up in this path we can read property again\n        dom.setAttributeNS(namespaces[prop], prop, nextValue);\n      } else {\n        if (process.env.NODE_ENV !== 'production') {\n          if (\n            prop === 'href' &&\n            isString(nextValue) &&\n            nextValue.startsWith('javascript:')\n          ) {\n            warning(\n              'Rendering links with javascript: URLs is not recommended. Use event handlers instead if you can. Inferno was passed \"' +\n                nextValue +\n                '\".',\n            );\n          }\n        }\n        dom.setAttribute(prop, nextValue);\n      }\n      break;\n  }\n}\n\nexport function mountProps(\n  vNode,\n  flags,\n  props,\n  dom,\n  isSVG,\n  animations: AnimationQueues,\n): void {\n  let hasControlledValue: boolean = false;\n  const isFormElement = (flags & VNodeFlags.FormElement) > 0;\n  if (isFormElement) {\n    hasControlledValue = isControlledFormElement(props);\n    if (hasControlledValue) {\n      addFormElementEventHandlers(flags, dom, props);\n    }\n  }\n  for (const prop in props) {\n    // do not add a hasOwnProperty check here, it affects performance\n    patchProp(\n      prop,\n      null,\n      props[prop],\n      dom,\n      isSVG,\n      hasControlledValue,\n      null,\n      animations,\n    );\n  }\n  if (isFormElement) {\n    processElement(flags, vNode, dom, props, true, hasControlledValue);\n  }\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/rendering.ts",
    "content": "import type {\n  InfernoNode,\n  VNode,\n  ContextObject,\n  ParentDOM,\n} from '../core/types';\nimport {\n  isFunction,\n  isInvalid,\n  isNullOrUndef,\n  throwError,\n  warning,\n} from 'inferno-shared';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { directClone } from '../core/implementation';\nimport { mount } from './mounting';\nimport { patch } from './patching';\nimport { remove } from './unmounting';\nimport {\n  AnimationQueues,\n  callAll,\n  callAllAnimationHooks,\n  EMPTY_OBJ,\n  renderCheck,\n} from './utils/common';\nimport { type DelegateEventTypes } from './events/delegation';\n\nconst hasDocumentAvailable: boolean = typeof document !== 'undefined';\n\nif (process.env.NODE_ENV !== 'production') {\n  if (hasDocumentAvailable && !document.body) {\n    warning(\n      'Inferno warning: you cannot initialize inferno without \"document.body\". Wait on \"DOMContentLoaded\" event, add script to bottom of body, or use async/defer attributes on script tag.',\n    );\n  }\n}\n\nlet documentBody: HTMLElement | null = null;\n\nif (hasDocumentAvailable) {\n  documentBody = document.body;\n  /*\n   * Defining $EV and $V properties on Node.prototype\n   * fixes v8 \"wrong map\" de-optimization\n   */\n\n  if (window.Node) {\n    (Node.prototype as any).$EV = null as DelegateEventTypes | null;\n    (Node.prototype as any).$V = null as DelegateEventTypes | null;\n  }\n}\n\n// noinspection JSUnusedAssignment\nexport function renderInternal(\n  input: VNode | InfernoNode,\n  parentDOM: ParentDOM,\n  callback: (() => void) | null,\n  context: ContextObject,\n): void {\n  // Development warning\n  if (process.env.NODE_ENV !== 'production') {\n    if (documentBody === parentDOM) {\n      throwError(\n        'you cannot render() to the \"document.body\". Use an empty element as a container instead.',\n      );\n    }\n    if (isInvalid(parentDOM)) {\n      throwError(\n        `render target ( DOM ) is mandatory, received ${\n          parentDOM === null ? 'null' : typeof parentDOM\n        }`,\n      );\n    }\n  }\n  const lifecycle: Array<() => void> = [];\n  const animations: AnimationQueues = new AnimationQueues();\n  const rootInput = (parentDOM as any).$V as VNode | null;\n\n  renderCheck.v = true;\n\n  if (isNullOrUndef(rootInput)) {\n    if (!isNullOrUndef(input)) {\n      if (((input as VNode).flags & VNodeFlags.InUse) !== 0) {\n        input = directClone(input as VNode);\n      }\n      mount(\n        input as VNode,\n        parentDOM as Element,\n        context,\n        false,\n        null,\n        lifecycle,\n        animations,\n      );\n      (parentDOM as any).$V = input;\n    }\n  } else {\n    if (isNullOrUndef(input)) {\n      remove(rootInput, parentDOM as Element, animations);\n      (parentDOM as any).$V = null;\n    } else {\n      if ((input as VNode).flags & VNodeFlags.InUse) {\n        input = directClone(input as VNode);\n      }\n      patch(\n        rootInput,\n        input as VNode,\n        parentDOM as Element,\n        context,\n        false,\n        null,\n        lifecycle,\n        animations,\n      );\n      (parentDOM as any).$V = input as VNode;\n    }\n  }\n  callAll(lifecycle);\n  callAllAnimationHooks(animations.componentDidAppear);\n\n  renderCheck.v = false;\n  if (isFunction(callback)) {\n    callback();\n  }\n}\n\nexport function render(\n  input: VNode | InfernoNode,\n  parentDOM: ParentDOM,\n  callback: (() => void) | null = null,\n  context: ContextObject = EMPTY_OBJ,\n): void {\n  renderInternal(input, parentDOM, callback, context);\n}\n\nexport function createRenderer(parentDOM?: ParentDOM) {\n  return function renderer(lastInput, nextInput, callback, context) {\n    if (!parentDOM) {\n      parentDOM = lastInput;\n    }\n    render(nextInput, parentDOM as ParentDOM, callback, context);\n  };\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/unmounting.ts",
    "content": "import type { VNode } from '../core/types';\nimport { isFunction, isNull, isNullOrUndef } from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport { syntheticEvents, unmountSyntheticEvent } from './events/delegation';\nimport {\n  AnimationQueues,\n  callAllAnimationHooks,\n  clearVNodeDOM,\n  EMPTY_OBJ,\n  findDOMFromVNode,\n  removeVNodeDOM,\n} from './utils/common';\nimport { unmountRef } from '../core/refs';\n\nexport function remove(\n  vNode: VNode,\n  parentDOM: Element,\n  animations: AnimationQueues,\n): void {\n  unmount(vNode, animations);\n  removeVNodeDOM(vNode, parentDOM, animations);\n}\n\nexport function unmount(vNode, animations: AnimationQueues): void {\n  const flags = vNode.flags;\n  const children = vNode.children;\n  let ref;\n\n  if ((flags & VNodeFlags.Element) !== 0) {\n    ref = vNode.ref;\n    const props = vNode.props;\n\n    unmountRef(ref);\n\n    const childFlags = vNode.childFlags;\n\n    if (!isNull(props)) {\n      const keys = Object.keys(props);\n\n      for (let i = 0, len = keys.length; i < len; i++) {\n        const key = keys[i];\n        if (syntheticEvents[key]) {\n          unmountSyntheticEvent(key, vNode.dom);\n        }\n      }\n    }\n\n    if (childFlags & ChildFlags.MultipleChildren) {\n      unmountAllChildren(children, animations);\n    } else if (childFlags === ChildFlags.HasVNodeChildren) {\n      unmount(children as VNode, animations);\n    }\n  } else if (children) {\n    if (flags & VNodeFlags.ComponentClass) {\n      if (isFunction(children.componentWillUnmount)) {\n        // TODO: Possible entrypoint\n        children.componentWillUnmount();\n      }\n\n      // If we have a componentWillDisappear on this component, block children from animating\n      let childAnimations = animations;\n      if (isFunction(children.componentWillDisappear)) {\n        childAnimations = new AnimationQueues();\n        addDisappearAnimationHook(\n          animations,\n          children,\n          children.$LI.dom,\n          flags,\n          undefined,\n        );\n      }\n\n      unmountRef(vNode.ref);\n      children.$UN = true;\n      unmount(children.$LI, childAnimations);\n    } else if (flags & VNodeFlags.ComponentFunction) {\n      // If we have a onComponentWillDisappear on this component, block children from animating\n      let childAnimations = animations;\n      ref = vNode.ref;\n      if (!isNullOrUndef(ref)) {\n        let domEl: Element | null = null;\n\n        if (isFunction(ref.onComponentWillUnmount)) {\n          domEl = findDOMFromVNode(vNode, true);\n          ref.onComponentWillUnmount(domEl, vNode.props || EMPTY_OBJ);\n        }\n        if (isFunction(ref.onComponentWillDisappear)) {\n          childAnimations = new AnimationQueues();\n          domEl = domEl || findDOMFromVNode(vNode, true);\n          addDisappearAnimationHook(\n            animations,\n            ref,\n            domEl as Element,\n            flags,\n            vNode.props,\n          );\n        }\n      }\n      unmount(children, childAnimations);\n    } else if (flags & VNodeFlags.Portal) {\n      remove(children as VNode, vNode.ref, animations);\n    } else if (flags & VNodeFlags.Fragment) {\n      if (vNode.childFlags & ChildFlags.MultipleChildren) {\n        unmountAllChildren(children, animations);\n      }\n    }\n  }\n}\n\nexport function unmountAllChildren(\n  children: VNode[],\n  animations: AnimationQueues,\n): void {\n  for (let i = 0, len = children.length; i < len; ++i) {\n    unmount(children[i], animations);\n  }\n}\n\nfunction createClearAllCallback(children, parentDOM) {\n  return function () {\n    // We need to remove children one by one because elements can be added during animation\n    if (parentDOM) {\n      for (let i = 0; i < children.length; i++) {\n        const vNode = children[i];\n        clearVNodeDOM(vNode, parentDOM, false);\n      }\n    }\n  };\n}\nexport function clearDOM(\n  parentDOM,\n  children: VNode[],\n  animations: AnimationQueues,\n): void {\n  if (animations.componentWillDisappear.length > 0) {\n    // Wait until animations are finished before removing actual dom nodes\n    // Be aware that the element could be removed by a later operation\n    callAllAnimationHooks(\n      animations.componentWillDisappear,\n      createClearAllCallback(children, parentDOM),\n    );\n  } else {\n    // Optimization for clearing dom\n    parentDOM.textContent = '';\n  }\n}\n\nexport function removeAllChildren(\n  dom: Element,\n  vNode: VNode,\n  children,\n  animations: AnimationQueues,\n): void {\n  unmountAllChildren(children, animations);\n\n  if (vNode.flags & VNodeFlags.Fragment) {\n    removeVNodeDOM(vNode, dom, animations);\n  } else {\n    clearDOM(dom, children, animations);\n  }\n}\n\n// Only add animations to queue in browser\nfunction addDisappearAnimationHook(\n  animations: AnimationQueues,\n  instanceOrRef,\n  dom: Element,\n  flags: VNodeFlags,\n  props,\n): void {\n  // @ts-expect-error TODO: Here is something weird check this behavior\n  animations.componentWillDisappear.push((callback) => {\n    if (flags & VNodeFlags.ComponentClass) {\n      instanceOrRef.componentWillDisappear(dom, callback);\n    } else if (flags & VNodeFlags.ComponentFunction) {\n      instanceOrRef.onComponentWillDisappear(dom, props, callback);\n    }\n  });\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/utils/common.ts",
    "content": "import type {\n  Inferno,\n  InfernoNode,\n  LinkedEvent,\n  VNode,\n} from './../../core/types';\nimport { isFunction, isNull, isNullOrUndef, isUndefined } from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport { isLinkEventObject } from '../events/linkEvent';\n\n// We need EMPTY_OBJ defined in one place.\n// It's used for comparison, so we can't inline it into shared\nexport const EMPTY_OBJ = {};\n\n// @ts-expect-error hack for fragment type\nexport const Fragment: Inferno.ExoticComponent<{ children?: InfernoNode }> =\n  '$F';\n\nexport interface MoveQueueItem {\n  parent: Element;\n  dom: Element;\n  next: Element;\n  fn: () => void;\n}\n\nexport class AnimationQueues {\n  public componentDidAppear: Array<() => void> = [];\n  public componentWillDisappear: Array<() => void> = [];\n  public componentWillMove: MoveQueueItem[] = [];\n}\n\nif (process.env.NODE_ENV !== 'production') {\n  Object.freeze(EMPTY_OBJ);\n}\n\nexport function normalizeEventName(name): keyof DocumentEventMap {\n  return name.substring(2).toLowerCase();\n}\n\nexport function appendChild(parentDOM, dom): void {\n  parentDOM.appendChild(dom);\n}\n\nexport function insertOrAppend(parentDOM: Element, newNode, nextNode): void {\n  if (isNull(nextNode)) {\n    appendChild(parentDOM, newNode);\n  } else {\n    parentDOM.insertBefore(newNode, nextNode);\n  }\n}\n\nexport function documentCreateElement(tag, isSVG: boolean): Element {\n  if (isSVG) {\n    return document.createElementNS('http://www.w3.org/2000/svg', tag);\n  }\n\n  return document.createElement(tag);\n}\n\nexport function replaceChild(parentDOM: Element, newDom, lastDom): void {\n  parentDOM.replaceChild(newDom, lastDom);\n}\n\nexport function removeChild(parentDOM: Element, childNode: Element): void {\n  parentDOM.removeChild(childNode);\n}\n\nexport function callAll(arrayFn: Array<() => void>): void {\n  for (let i = 0; i < arrayFn.length; i++) {\n    arrayFn[i]();\n  }\n}\n\nfunction findChildVNode(\n  vNode: VNode,\n  startEdge: boolean,\n  flags: VNodeFlags,\n): InfernoNode {\n  const children = vNode.children;\n\n  if ((flags & VNodeFlags.ComponentClass) !== 0) {\n    return (children as any).$LI;\n  }\n\n  if ((flags & VNodeFlags.Fragment) !== 0) {\n    return vNode.childFlags === ChildFlags.HasVNodeChildren\n      ? (children as VNode)\n      : (children as VNode[])[startEdge ? 0 : (children as VNode[]).length - 1];\n  }\n\n  return children;\n}\n\nexport function findDOMFromVNode(\n  vNode: VNode,\n  startEdge: boolean,\n): Element | null {\n  let flags: VNodeFlags;\n  let v: VNode | null = vNode;\n\n  while (!isNullOrUndef(v)) {\n    flags = v.flags;\n\n    if ((flags & VNodeFlags.DOMRef) !== 0) {\n      return v.dom;\n    }\n\n    v = findChildVNode(v, startEdge, flags) as VNode | null;\n  }\n\n  return null;\n}\n\nexport function callAllAnimationHooks(\n  animationQueue: Array<() => void>,\n  callback?: () => void,\n): void {\n  let animationsLeft: number = animationQueue.length;\n  // Picking from the top because it is faster, invocation order should be irrelevant\n  // since all animations are to be run, and we can't predict the order in which they complete.\n  let fn;\n  while ((fn = animationQueue.pop()) !== undefined) {\n    fn(() => {\n      if (--animationsLeft <= 0 && isFunction(callback)) {\n        callback();\n      }\n    });\n  }\n}\n\nexport function callAllMoveAnimationHooks(\n  animationQueue: MoveQueueItem[],\n): void {\n  // Start the animations.\n  for (let i = 0; i < animationQueue.length; i++) {\n    animationQueue[i].fn();\n  }\n  // Perform the actual DOM moves when all measurements of initial\n  // position have been performed. The rest of the animations are done\n  // async.\n  for (let i = 0; i < animationQueue.length; i++) {\n    const tmp = animationQueue[i];\n    insertOrAppend(tmp.parent, tmp.dom, tmp.next);\n  }\n  animationQueue.splice(0, animationQueue.length);\n}\n\nexport function clearVNodeDOM(\n  vNode: VNode | null,\n  parentDOM: Element,\n  deferredRemoval: boolean,\n): void {\n  while (!isNullOrUndef(vNode)) {\n    const flags = vNode.flags;\n\n    if ((flags & VNodeFlags.DOMRef) !== 0) {\n      // On deferred removals the node might disappear because of later operations\n      if (!deferredRemoval || (vNode.dom as Element).parentNode === parentDOM) {\n        removeChild(parentDOM, vNode.dom as Element);\n      }\n      return;\n    }\n    const children = vNode.children as any;\n\n    if ((flags & VNodeFlags.ComponentClass) !== 0) {\n      vNode = children.$LI;\n    }\n    if ((flags & VNodeFlags.ComponentFunction) !== 0) {\n      vNode = children;\n    }\n    if ((flags & VNodeFlags.Fragment) !== 0) {\n      if ((vNode as VNode).childFlags === ChildFlags.HasVNodeChildren) {\n        vNode = children;\n      } else {\n        for (let i = 0, len = children.length; i < len; ++i) {\n          clearVNodeDOM(children[i], parentDOM, false);\n        }\n        return;\n      }\n    }\n  }\n}\n\nfunction createDeferComponentClassRemovalCallback(vNode, parentDOM) {\n  return function () {\n    // Mark removal as deferred to trigger check that node still exists\n    clearVNodeDOM(vNode, parentDOM, true);\n  };\n}\n\nexport function removeVNodeDOM(\n  vNode: VNode,\n  parentDOM: Element,\n  animations: AnimationQueues,\n): void {\n  if (animations.componentWillDisappear.length > 0) {\n    // Wait until animations are finished before removing actual dom nodes\n    callAllAnimationHooks(\n      animations.componentWillDisappear,\n      createDeferComponentClassRemovalCallback(vNode, parentDOM),\n    );\n  } else {\n    clearVNodeDOM(vNode, parentDOM, false);\n  }\n}\n\nfunction addMoveAnimationHook(\n  animations: AnimationQueues,\n  parentVNode,\n  refOrInstance,\n  dom: Element,\n  parentDOM: Element,\n  nextNode: Element,\n  flags,\n  props?,\n): void {\n  animations.componentWillMove.push({\n    dom,\n    fn: () => {\n      if ((flags & VNodeFlags.ComponentClass) !== 0) {\n        refOrInstance.componentWillMove(parentVNode, parentDOM, dom);\n      } else if ((flags & VNodeFlags.ComponentFunction) !== 0) {\n        refOrInstance.onComponentWillMove(parentVNode, parentDOM, dom, props);\n      }\n    },\n    next: nextNode,\n    parent: parentDOM,\n  });\n}\n\nexport function moveVNodeDOM(\n  parentVNode,\n  vNode,\n  parentDOM,\n  nextNode,\n  animations: AnimationQueues,\n): void {\n  let refOrInstance;\n  let instanceProps;\n  const instanceFlags = vNode.flags;\n\n  while (!isNullOrUndef(vNode)) {\n    const flags = vNode.flags;\n\n    if ((flags & VNodeFlags.DOMRef) !== 0) {\n      if (\n        !isNullOrUndef(refOrInstance) &&\n        (isFunction(refOrInstance.componentWillMove) ||\n          isFunction(refOrInstance.onComponentWillMove))\n      ) {\n        addMoveAnimationHook(\n          animations,\n          parentVNode,\n          refOrInstance,\n          vNode.dom,\n          parentDOM,\n          nextNode,\n          instanceFlags,\n          instanceProps,\n        );\n      } else {\n        // TODO: Should we delay this too to support mixing animated moves with regular?\n        insertOrAppend(parentDOM, vNode.dom, nextNode);\n      }\n      return;\n    }\n    const children = vNode.children;\n\n    if ((flags & VNodeFlags.ComponentClass) !== 0) {\n      refOrInstance = vNode.children;\n      // TODO: We should probably deprecate this in V9 since it is inconsitent with other class component hooks\n      instanceProps = vNode.props;\n      vNode = children.$LI;\n    } else if ((flags & VNodeFlags.ComponentFunction) !== 0) {\n      refOrInstance = vNode.ref;\n      instanceProps = vNode.props;\n      vNode = children;\n    } else if ((flags & VNodeFlags.Fragment) !== 0) {\n      if (vNode.childFlags === ChildFlags.HasVNodeChildren) {\n        vNode = children;\n      } else {\n        for (let i = 0, len = children.length; i < len; ++i) {\n          moveVNodeDOM(\n            parentVNode,\n            children[i],\n            parentDOM,\n            nextNode,\n            animations,\n          );\n        }\n        return;\n      }\n    }\n  }\n}\n\nexport function getComponentName(instance: any): string {\n  // TODO: Fallback for IE\n  return (\n    instance.name ??\n    instance.displayName ??\n    instance.constructor.name ??\n    ((instance as any).toString().match(/^function\\s*([^\\s(]+)/) || [])[1]\n  );\n}\n\nexport function createDerivedState<TState>(\n  instance,\n  nextProps,\n  state: TState,\n): TState {\n  if (isFunction(instance.constructor.getDerivedStateFromProps)) {\n    return {\n      ...state,\n      ...instance.constructor.getDerivedStateFromProps(nextProps, state),\n    };\n  }\n\n  return state;\n}\n\nexport const renderCheck = {\n  v: false,\n};\n\nexport const options: {\n  createVNode: ((vNode: VNode) => void) | null;\n  reactStyles?: boolean;\n} = {\n  createVNode: null,\n};\n\nexport function setTextContent(dom: Element, children): void {\n  dom.textContent = children;\n}\n\n// Calling this function assumes, nextValue is linkEvent\nexport function isLastValueSameLinkEvent(lastValue, nextValue): boolean {\n  return (\n    isLinkEventObject(lastValue) &&\n    lastValue.event === (nextValue as LinkedEvent<any, any>).event &&\n    lastValue.data === (nextValue as LinkedEvent<any, any>).data\n  );\n}\n\nexport function mergeUnsetProperties<TTo, TFrom>(\n  to: TTo,\n  from: TFrom,\n): TTo & TFrom {\n  for (const propName in from) {\n    // @ts-expect-error merge objects\n    if (isUndefined(to[propName])) {\n      // @ts-expect-error merge objects\n      to[propName] = from[propName];\n    }\n  }\n\n  // @ts-expect-error merge objects\n  return to;\n}\n\nexport function safeCall1(\n  method: Function | null | undefined,\n  arg1: any,\n): boolean {\n  return isFunction(method) && (method(arg1), true);\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/utils/componentUtil.ts",
    "content": "import type { ContextObject, InfernoNode, VNode } from './../../core/types';\nimport type { Component } from './../../core/component';\nimport { isFunction, isNull, warning } from 'inferno-shared';\nimport { createDerivedState, EMPTY_OBJ, getComponentName } from './common';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { normalizeRoot } from '../../core/implementation';\n\nfunction warnAboutOldLifecycles(component: any): void {\n  const oldLifecycles: string[] = [];\n\n  // Don't warn about react polyfilled components.\n  if (\n    component.componentWillMount &&\n    component.componentWillMount.__suppressDeprecationWarning !== true\n  ) {\n    oldLifecycles.push('componentWillMount');\n  }\n\n  if (\n    component.componentWillReceiveProps &&\n    component.componentWillReceiveProps.__suppressDeprecationWarning !== true\n  ) {\n    oldLifecycles.push('componentWillReceiveProps');\n  }\n\n  if (\n    component.componentWillUpdate &&\n    component.componentWillUpdate.__suppressDeprecationWarning !== true\n  ) {\n    oldLifecycles.push('componentWillUpdate');\n  }\n\n  if (oldLifecycles.length > 0) {\n    warning(`\n      Warning: Unsafe legacy lifecycles will not be called for components using new component APIs.\n      ${getComponentName(component)} contains the following legacy lifecycles:\n      ${oldLifecycles.join('\\n')}\n      The above lifecycles should be removed.\n    `);\n  }\n}\n\nexport function renderNewInput(instance, props, context): VNode {\n  const nextInput = normalizeRoot(\n    instance.render(props, instance.state, context),\n  );\n\n  let childContext = context;\n  if (isFunction(instance.getChildContext)) {\n    childContext = { ...context, ...instance.getChildContext() };\n  }\n  instance.$CX = childContext;\n\n  return nextInput;\n}\n\nexport function createClassComponentInstance(\n  vNode: VNode,\n  ComponentCtr,\n  props,\n  context: ContextObject,\n  isSVG: boolean,\n  lifecycle: Array<() => void>,\n): Component<any, any> {\n  const instance = new ComponentCtr(props, context);\n  const usesNewAPI = (instance.$N = Boolean(\n    ComponentCtr.getDerivedStateFromProps || instance.getSnapshotBeforeUpdate,\n  ));\n\n  instance.$SVG = isSVG;\n  instance.$L = lifecycle;\n\n  if (process.env.NODE_ENV !== 'production') {\n    if (instance.getDerivedStateFromProps) {\n      warning(\n        `${getComponentName(\n          instance,\n        )} getDerivedStateFromProps() is defined as an instance method and will be ignored. Instead, declare it as a static method.`,\n      );\n    }\n    if (usesNewAPI) {\n      warnAboutOldLifecycles(instance);\n    }\n  }\n\n  vNode.children = instance;\n  instance.$BS = false;\n  instance.context = context;\n  if (instance.props === EMPTY_OBJ) {\n    instance.props = props;\n  }\n  if (!usesNewAPI) {\n    if (isFunction(instance.componentWillMount)) {\n      instance.$BR = true;\n      instance.componentWillMount();\n\n      const pending = instance.$PS;\n\n      if (!isNull(pending)) {\n        const state = instance.state;\n\n        if (isNull(state)) {\n          instance.state = pending;\n        } else {\n          for (const key in pending) {\n            state[key] = pending[key];\n          }\n        }\n        instance.$PS = null;\n      }\n\n      instance.$BR = false;\n    }\n  } else {\n    instance.state = createDerivedState(instance, props, instance.state);\n  }\n\n  instance.$LI = renderNewInput(instance, props, context);\n\n  return instance;\n}\n\nexport function renderFunctionalComponent(\n  vNode: VNode,\n  context: ContextObject,\n): InfernoNode {\n  const props = vNode.props || EMPTY_OBJ;\n  return vNode.flags & VNodeFlags.ForwardRef\n    ? vNode.type.render(props, vNode.ref, context)\n    : vNode.type(props, context);\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/utils/innerHTML.ts",
    "content": "export function isSameInnerHTML(dom: Element, innerHTML: string): boolean {\n  const temp = document.createElement('i');\n\n  temp.innerHTML = innerHTML;\n  return temp.innerHTML === dom.innerHTML;\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/wrappers/InputWrapper.ts",
    "content": "import { isNullOrUndef } from 'inferno-shared';\nimport { createWrappedFunction } from './wrapper';\nimport { attachEvent } from '../events/attachEvent';\n\nexport function isCheckedType(type): boolean {\n  return type === 'checkbox' || type === 'radio';\n}\n\nconst onTextInputChange = createWrappedFunction('onInput', applyValueInput);\n\nconst wrappedOnChange = createWrappedFunction(\n  ['onClick', 'onChange'],\n  applyValueInput,\n);\n\nfunction stopPropagationWrapper(event) {\n  event.stopPropagation();\n}\n(stopPropagationWrapper as any).wrapped = true;\n\nexport function inputEvents(dom, nextPropsOrEmpty): void {\n  if (isCheckedType(nextPropsOrEmpty.type)) {\n    attachEvent(dom, 'change', wrappedOnChange);\n    attachEvent(dom, 'click', stopPropagationWrapper);\n  } else {\n    attachEvent(dom, 'input', onTextInputChange);\n  }\n}\n\nexport function applyValueInput(nextPropsOrEmpty, dom): void {\n  const type = nextPropsOrEmpty.type;\n  const value = nextPropsOrEmpty.value;\n  const checked = nextPropsOrEmpty.checked;\n  const multiple = nextPropsOrEmpty.multiple;\n  const defaultValue = nextPropsOrEmpty.defaultValue;\n  const hasValue = !isNullOrUndef(value);\n\n  if (type != null && type !== dom.type) {\n    dom.setAttribute('type', type);\n  }\n  if (!isNullOrUndef(multiple) && multiple !== dom.multiple) {\n    dom.multiple = multiple;\n  }\n  if (!isNullOrUndef(defaultValue) && !hasValue) {\n    dom.defaultValue = defaultValue + '';\n  }\n  if (isCheckedType(type)) {\n    if (hasValue) {\n      dom.value = value;\n    }\n    if (!isNullOrUndef(checked)) {\n      dom.checked = checked;\n    }\n  } else {\n    if (hasValue && dom.value !== value) {\n      dom.defaultValue = value;\n      dom.value = value;\n    } else if (!isNullOrUndef(checked)) {\n      dom.checked = checked;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/wrappers/SelectWrapper.ts",
    "content": "import { isArray, isNullOrUndef, isNumber } from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport { EMPTY_OBJ } from '../utils/common';\nimport { createWrappedFunction } from './wrapper';\nimport { attachEvent } from '../events/attachEvent';\nimport { type VNode } from '../../core/types';\nimport { type Component } from '../../core/component';\n\nfunction updateChildOptions(vNode: VNode, value): void {\n  if (vNode.type === 'option') {\n    updateChildOption(vNode, value);\n  } else {\n    const children = vNode.children;\n    const flags = vNode.flags;\n\n    if ((flags & VNodeFlags.ComponentClass) !== 0) {\n      updateChildOptions((children as Component).$LI, value);\n    } else if ((flags & VNodeFlags.ComponentFunction) !== 0) {\n      updateChildOptions(children as VNode, value);\n    } else if (vNode.childFlags === ChildFlags.HasVNodeChildren) {\n      updateChildOptions(children as VNode, value);\n    } else if ((vNode.childFlags & ChildFlags.MultipleChildren) !== 0) {\n      for (let i = 0, len = (children as VNode[]).length; i < len; ++i) {\n        updateChildOptions((children as VNode[])[i], value);\n      }\n    }\n  }\n}\n\nfunction updateChildOption(vNode: VNode, value: unknown): void {\n  const props: any = vNode.props ?? EMPTY_OBJ;\n  const propsValue = props.value;\n  const dom = vNode.dom as any;\n\n  // we do this as multiple prop may have changed\n  dom.value = propsValue;\n\n  if (propsValue === value || (isArray(value) && value.includes(propsValue))) {\n    dom.selected = true;\n  } else if (!isNullOrUndef(value) || !isNullOrUndef(props.selected)) {\n    dom.selected = Boolean(props.selected);\n  }\n}\n\nconst onSelectChange = createWrappedFunction('onChange', applyValueSelect);\n\nexport function selectEvents(dom): void {\n  attachEvent(dom, 'change', onSelectChange);\n}\n\nexport function applyValueSelect(\n  nextPropsOrEmpty,\n  dom: any,\n  mounting: boolean,\n  vNode,\n): void {\n  const multiplePropInBoolean = Boolean(nextPropsOrEmpty.multiple);\n  if (\n    !isNullOrUndef(nextPropsOrEmpty.multiple) &&\n    multiplePropInBoolean !== dom.multiple\n  ) {\n    dom.multiple = multiplePropInBoolean;\n  }\n  const index = nextPropsOrEmpty.selectedIndex;\n  if (index === -1) {\n    dom.selectedIndex = -1;\n  }\n  const childFlags = vNode.childFlags;\n\n  if (childFlags !== ChildFlags.HasInvalidChildren) {\n    let value = nextPropsOrEmpty.value;\n    if (isNumber(index) && index > -1 && !isNullOrUndef(dom.options[index])) {\n      value = dom.options[index].value;\n    }\n    if (mounting && isNullOrUndef(value)) {\n      value = nextPropsOrEmpty.defaultValue;\n    }\n    updateChildOptions(vNode, value);\n  }\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/wrappers/TextareaWrapper.ts",
    "content": "import { isFunction, isNullOrUndef } from 'inferno-shared';\nimport { createWrappedFunction } from './wrapper';\nimport { attachEvent } from '../events/attachEvent';\nimport { type NonEmptyProps } from '../../core/types';\n\nconst onTextareaInputChange = createWrappedFunction(\n  'onInput',\n  applyValueTextArea,\n);\nconst wrappedOnChange = createWrappedFunction('onChange');\n\nexport function textAreaEvents(dom, nextPropsOrEmpty): void {\n  attachEvent(dom, 'input', onTextareaInputChange);\n  if (isFunction(nextPropsOrEmpty.onChange)) {\n    attachEvent(dom, 'change', wrappedOnChange);\n  }\n}\n\nexport function applyValueTextArea(\n  nextPropsOrEmpty: NonEmptyProps,\n  dom,\n  mounting: boolean,\n): void {\n  const value = nextPropsOrEmpty.value;\n  const domValue = dom.value;\n\n  if (isNullOrUndef(value)) {\n    if (mounting) {\n      const defaultValue = nextPropsOrEmpty.defaultValue;\n\n      if (!isNullOrUndef(defaultValue) && defaultValue !== domValue) {\n        dom.defaultValue = defaultValue;\n        dom.value = defaultValue;\n      }\n    }\n  } else if (domValue !== value) {\n    /* There is value so keep it controlled */\n    dom.defaultValue = value;\n    dom.value = value;\n  }\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/wrappers/processElement.ts",
    "content": "import type { VNode } from '../../core/types';\nimport { isNullOrUndef } from 'inferno-shared';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { applyValueInput, inputEvents, isCheckedType } from './InputWrapper';\nimport { applyValueSelect, selectEvents } from './SelectWrapper';\nimport { applyValueTextArea, textAreaEvents } from './TextareaWrapper';\n\nexport function processElement(\n  flags: VNodeFlags,\n  vNode: VNode,\n  dom: Element,\n  nextPropsOrEmpty,\n  mounting: boolean,\n  isControlled: boolean,\n): void {\n  if ((flags & VNodeFlags.InputElement) !== 0) {\n    applyValueInput(nextPropsOrEmpty, dom);\n  } else if ((flags & VNodeFlags.SelectElement) !== 0) {\n    applyValueSelect(nextPropsOrEmpty, dom, mounting, vNode);\n  } else if ((flags & VNodeFlags.TextareaElement) !== 0) {\n    applyValueTextArea(nextPropsOrEmpty, dom, mounting);\n  }\n  if (isControlled) {\n    (dom as any).$V = vNode;\n  }\n}\n\nexport function addFormElementEventHandlers(\n  flags: VNodeFlags,\n  dom: Element,\n  nextPropsOrEmpty,\n): void {\n  if ((flags & VNodeFlags.InputElement) !== 0) {\n    inputEvents(dom, nextPropsOrEmpty);\n  } else if ((flags & VNodeFlags.SelectElement) !== 0) {\n    selectEvents(dom);\n  } else if ((flags & VNodeFlags.TextareaElement) !== 0) {\n    textAreaEvents(dom, nextPropsOrEmpty);\n  }\n}\n\nexport function isControlledFormElement(nextPropsOrEmpty): boolean {\n  return isCheckedType(nextPropsOrEmpty.type)\n    ? !isNullOrUndef(nextPropsOrEmpty.checked)\n    : !isNullOrUndef(nextPropsOrEmpty.value);\n}\n"
  },
  {
    "path": "packages/inferno/src/DOM/wrappers/wrapper.ts",
    "content": "import { isFunction, isNullOrUndef, isString } from 'inferno-shared';\nimport { EMPTY_OBJ } from '../utils/common';\nimport { type NonEmptyProps, type VNode } from '../../core/types';\n\nfunction triggerEventListener(\n  props: NonEmptyProps,\n  methodName: string,\n  e: any,\n): void {\n  const listener = props[methodName] as any;\n\n  if (listener) {\n    if (listener.event) {\n      listener.event(listener.data, e);\n    } else {\n      listener(e);\n    }\n  } else {\n    const nativeListenerName = methodName.toLowerCase();\n\n    if (isFunction(props[nativeListenerName])) {\n      (props[nativeListenerName] as (e) => void)(e);\n    }\n  }\n}\n\nexport function createWrappedFunction(\n  methodName: string | string[],\n  applyValue?: (\n    newProps: NonEmptyProps,\n    dom: any,\n    isMounting: boolean,\n    newVNode: VNode,\n  ) => void,\n): (e: Event) => void {\n  const fnWrapper = function fnWrapper(e: Event): void {\n    const vNode = this.$V as VNode;\n    // If vNode is gone by the time event fires, no-op\n    if (isNullOrUndef(vNode)) {\n      return;\n    }\n    const props = vNode.props ?? EMPTY_OBJ;\n    const dom = vNode.dom;\n\n    if (isString(methodName)) {\n      triggerEventListener(props, methodName, e);\n    } else {\n      for (let i = 0; i < methodName.length; ++i) {\n        triggerEventListener(props, methodName[i], e);\n      }\n    }\n\n    if (isFunction(applyValue)) {\n      const newVNode = this.$V;\n      const newProps = newVNode.props ?? EMPTY_OBJ;\n\n      applyValue(newProps, dom, false, newVNode);\n    }\n  };\n\n  Object.defineProperty(fnWrapper, 'wrapped', {\n    configurable: false,\n    enumerable: false,\n    value: true,\n    writable: false,\n  });\n\n  return fnWrapper;\n}\n"
  },
  {
    "path": "packages/inferno/src/core/component.ts",
    "content": "import type { Inferno, InfernoNode, IComponent, VNode } from './types';\nimport { isFunction, isNullOrUndef, throwError } from 'inferno-shared';\nimport { updateClassComponent } from '../DOM/patching';\nimport {\n  AnimationQueues,\n  callAll,\n  callAllAnimationHooks,\n  EMPTY_OBJ,\n  findDOMFromVNode,\n  renderCheck,\n} from '../DOM/utils/common';\n\nconst COMPONENTS_QUEUE: Array<Component<any, any>> = [];\n\nconst nextTick = Promise.resolve().then.bind(Promise.resolve());\nlet microTaskPending = false;\n\nfunction queueStateChanges<P, S>(\n  component: Component<P, S>,\n  newState: any,\n  callback: (() => void) | undefined,\n  force: boolean,\n): void {\n  const pending = component.$PS;\n\n  if (isFunction(newState)) {\n    newState = newState(\n      pending ? { ...component.state, ...pending } : component.state,\n      component.props,\n      component.context,\n    );\n  }\n\n  if (isNullOrUndef(pending)) {\n    component.$PS = newState;\n  } else {\n    for (const stateKey in newState) {\n      pending[stateKey] = newState[stateKey];\n    }\n  }\n\n  if (!component.$BR) {\n    if (!renderCheck.v) {\n      if (COMPONENTS_QUEUE.length === 0) {\n        applyState(component, force);\n        if (isFunction(callback)) {\n          callback.call(component);\n        }\n        return;\n      }\n    }\n    if (!COMPONENTS_QUEUE.includes(component)) {\n      COMPONENTS_QUEUE.push(component);\n    }\n    if (force) {\n      component.$F = true;\n    }\n    if (!microTaskPending) {\n      microTaskPending = true;\n      nextTick(rerender);\n    }\n    if (isFunction(callback)) {\n      let QU = component.$QU;\n\n      if (!QU) {\n        QU = component.$QU = [] as Array<() => void>;\n      }\n      QU.push(callback);\n    }\n  } else if (isFunction(callback)) {\n    (component.$L as Array<() => void>).push(callback.bind(component));\n  }\n}\n\nfunction callSetStateCallbacks(component): void {\n  const queue = component.$QU;\n\n  for (let i = 0; i < queue.length; ++i) {\n    queue[i].call(component);\n  }\n\n  component.$QU = null;\n}\n\nexport function rerender(): void {\n  let component: Component<any, any> | undefined;\n  microTaskPending = false;\n\n  while ((component = COMPONENTS_QUEUE.shift())) {\n    if (!component.$UN) {\n      const force = component.$F;\n      component.$F = false;\n      applyState(component, force);\n\n      if (component.$QU) {\n        callSetStateCallbacks(component);\n      }\n    }\n  }\n}\n\nfunction applyState<P, S>(component: Component<P, S>, force: boolean): void {\n  if (force || !component.$BR) {\n    const pendingState = component.$PS;\n\n    component.$PS = null;\n\n    const lifecycle: Array<() => void> = [];\n    const animations: AnimationQueues = new AnimationQueues();\n\n    renderCheck.v = true;\n\n    updateClassComponent(\n      component,\n      { ...component.state, ...pendingState },\n      component.props,\n      (findDOMFromVNode(component.$LI, true) as Element).parentNode as Element,\n      component.context,\n      component.$SVG,\n      force,\n      null,\n      lifecycle,\n      animations,\n    );\n    callAll(lifecycle);\n    callAllAnimationHooks(animations.componentDidAppear);\n\n    renderCheck.v = false;\n  } else {\n    component.state = component.$PS as any;\n    component.$PS = null;\n  }\n}\nexport type ComponentType<P = Record<string, unknown>> =\n  | typeof Component<P>\n  | Inferno.StatelessComponent<P>;\n\nexport abstract class Component<\n  P = Record<string, unknown>,\n  S = Record<string, unknown>,\n> implements IComponent<P, S>\n{\n  // Public\n  public state: Readonly<S | null> = null;\n  public props: Readonly<{ children?: InfernoNode }> & Readonly<P>;\n  public context: any;\n  public displayName?: string;\n\n  // Internal properties\n  public $BR: boolean = false; // BLOCK RENDER\n  public $BS: boolean = true; // BLOCK STATE\n  public $PS: Partial<S> | null = null; // PENDING STATE (PARTIAL or FULL)\n  public $LI: any = null; // LAST INPUT\n  public $UN: boolean = false; // UNMOUNTED\n  public $CX: any = null; // CHILDCONTEXT\n  public $QU: Array<() => void> | null = null; // QUEUE\n  public $N: boolean = false; // Uses new lifecycle API Flag\n  public $SSR?: boolean; // Server side rendering flag, true when rendering on server, non existent on client\n  public $L: Array<() => void> | null = null; // Current lifecycle of this component\n  public $SVG: boolean = false; // Flag to keep track if component is inside SVG tree\n  public $F: boolean = false; // Force update flag\n\n  constructor(props?: P, context?: any) {\n    this.props = (props || EMPTY_OBJ) as Readonly<{ children?: InfernoNode }> &\n      Readonly<P>;\n    this.context = context || EMPTY_OBJ; // context should not be mutable\n  }\n\n  public forceUpdate(callback?: (() => void) | undefined): void {\n    if (this.$UN) {\n      return;\n    }\n    // Do not allow double render during force update\n    queueStateChanges(this, {} as any, callback, true);\n  }\n\n  public setState<K extends keyof S>(\n    newState:\n      | ((\n          prevState: Readonly<S>,\n          props: Readonly<{ children?: InfernoNode } & P>,\n        ) => Pick<S, K> | S | null)\n      | (Pick<S, K> | S | null),\n    callback?: () => void,\n  ): void {\n    if (this.$UN) {\n      return;\n    }\n    if (!this.$BS) {\n      queueStateChanges(this, newState, callback, false);\n    } else {\n      // Development warning\n      if (process.env.NODE_ENV !== 'production') {\n        throwError(\n          'cannot update state via setState() in constructor. Instead, assign to `this.state` directly or define a `state = {};`',\n        );\n      }\n    }\n  }\n\n  public componentDidMount?(): void;\n\n  public componentWillMount?(): void;\n\n  public componentWillReceiveProps?(\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n    nextContext: any,\n  ): void;\n\n  public shouldComponentUpdate?(\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n    nextState: Readonly<S>,\n    context: any,\n  ): boolean;\n\n  public componentWillUpdate?(\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n    nextState: Readonly<S>,\n    context: any,\n  ): void;\n\n  public componentDidUpdate?(\n    prevProps: Readonly<{ children?: InfernoNode } & P>,\n    prevState: Readonly<S>,\n    snapshot: any,\n  ): void;\n\n  public componentWillUnmount?(): void;\n\n  public componentDidAppear?(domNode: Element): void;\n\n  public componentWillDisappear?(domNode: Element, callback: () => void): void;\n\n  public componentWillMove?(\n    parentVNode: VNode,\n    parentDOM: Element,\n    dom: Element,\n  ): void;\n\n  public getChildContext?(): void;\n\n  public getSnapshotBeforeUpdate?(\n    prevProps: Readonly<{ children?: InfernoNode } & P>,\n    prevState: Readonly<S>,\n  ): any;\n\n  public static defaultProps?: Record<string, unknown> | null = null;\n\n  public static getDerivedStateFromProps?(nextProps: any, state: any): any;\n\n  /* eslint-disable */\n  // @ts-ignore\n  public render(props: Readonly<{ children?: InfernoNode } & P>, state: Readonly<S>, context: any): InfernoNode {\n    return null;\n  }\n}\n"
  },
  {
    "path": "packages/inferno/src/core/implementation.ts",
    "content": "import type {\n  ForwardRef,\n  InfernoNode,\n  ParentDOM,\n  Ref,\n  Refs,\n  VNode,\n} from './types';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport {\n  isArray,\n  isFunction,\n  isInvalid,\n  isNull,\n  isNullOrUndef,\n  isString,\n  isStringOrNumber,\n  throwError,\n} from 'inferno-shared';\nimport {\n  throwIfObjectIsNotVNode,\n  validateChildFlags,\n  validateVNodeElementChildren,\n} from './validate';\nimport { Fragment, mergeUnsetProperties, options } from './../DOM/utils/common';\nimport { type Component, type ComponentType } from './component';\n\nconst keyPrefix = '$';\n\nfunction V(\n  childFlags: ChildFlags,\n  children,\n  className: string | null | undefined,\n  flags: VNodeFlags,\n  key,\n  props,\n  ref,\n  type,\n): void {\n  if (process.env.NODE_ENV !== 'production') {\n    this.isValidated = false;\n  }\n  this.childFlags = childFlags;\n  this.children = children;\n  this.className = className;\n  this.dom = null;\n  this.flags = flags;\n  this.key = key === void 0 ? null : key;\n  this.props = props === void 0 ? null : props;\n  this.ref = ref === void 0 ? null : ref;\n  this.type = type;\n}\n\nexport function createVNode<P>(\n  flags: VNodeFlags,\n  type: string,\n  className?: string | null,\n  children?: InfernoNode,\n  childFlags?: ChildFlags,\n  props?: Readonly<P> | null,\n  key?: string | number | null,\n  ref?: Ref | Refs<P> | null,\n): VNode {\n  if (process.env.NODE_ENV !== 'production') {\n    if (flags & VNodeFlags.Component) {\n      throwError(\n        'Creating Component vNodes using createVNode is not allowed. Use Inferno.createComponentVNode method.',\n      );\n    }\n  }\n  const childFlag: ChildFlags =\n    childFlags === void 0 ? ChildFlags.HasInvalidChildren : childFlags;\n  const vNode = new V(\n    childFlag,\n    children,\n    className,\n    flags,\n    key,\n    props,\n    ref,\n    type,\n  ) as VNode;\n\n  if (options.createVNode) {\n    options.createVNode(vNode);\n  }\n\n  if (childFlag === ChildFlags.UnknownChildren) {\n    normalizeChildren(vNode, vNode.children);\n  }\n\n  if (process.env.NODE_ENV !== 'production') {\n    if (childFlag !== ChildFlags.UnknownChildren) {\n      validateChildFlags(vNode);\n    }\n    validateVNodeElementChildren(vNode);\n  }\n\n  return vNode;\n}\n\nfunction mergeDefaultHooks(flags, type, ref) {\n  if (flags & VNodeFlags.ComponentClass) {\n    return ref;\n  }\n\n  const defaultHooks = (flags & VNodeFlags.ForwardRef ? type.render : type)\n    .defaultHooks;\n\n  if (isNullOrUndef(defaultHooks)) {\n    return ref;\n  }\n\n  if (isNullOrUndef(ref)) {\n    return defaultHooks;\n  }\n\n  return mergeUnsetProperties(ref, defaultHooks);\n}\n\nfunction mergeDefaultProps(flags, type, props) {\n  // set default props\n  const defaultProps = (flags & VNodeFlags.ForwardRef ? type.render : type)\n    .defaultProps;\n\n  if (isNullOrUndef(defaultProps)) {\n    return props;\n  }\n\n  if (isNullOrUndef(props)) {\n    return { ...defaultProps };\n  }\n\n  return mergeUnsetProperties(props, defaultProps);\n}\n\nfunction resolveComponentFlags(flags: VNodeFlags, type): VNodeFlags {\n  if (flags & VNodeFlags.ComponentKnown) {\n    return flags;\n  }\n\n  if (type.prototype?.render) {\n    return VNodeFlags.ComponentClass;\n  }\n\n  if (type.render) {\n    return VNodeFlags.ForwardRefComponent;\n  }\n\n  return VNodeFlags.ComponentFunction;\n}\n\nexport function createComponentVNode<P>(\n  flags: VNodeFlags,\n  type:\n    | Function\n    | ComponentType<P>\n    | Component<P, unknown>\n    | ForwardRef<P, unknown>,\n  props?: Readonly<P> | null,\n  key?: null | string | number,\n  ref?: Ref | Refs<P> | null,\n): VNode {\n  if (process.env.NODE_ENV !== 'production') {\n    if ((flags & VNodeFlags.HtmlElement) !== 0) {\n      throwError(\n        'Creating element vNodes using createComponentVNode is not allowed. Use Inferno.createVNode method.',\n      );\n    }\n  }\n\n  flags = resolveComponentFlags(flags, type);\n\n  const vNode = new V(\n    ChildFlags.HasInvalidChildren,\n    null,\n    null,\n    flags,\n    key,\n    mergeDefaultProps(flags, type, props),\n    mergeDefaultHooks(flags, type, ref),\n    type,\n  ) as VNode;\n\n  if (isFunction(options.createVNode)) {\n    options.createVNode(vNode);\n  }\n\n  return vNode;\n}\n\nexport function createTextVNode(\n  text?: string | boolean | null | number,\n  key?: string | number | null,\n): VNode {\n  return new V(\n    ChildFlags.HasInvalidChildren,\n    isNullOrUndef(text) || text === true || text === false ? '' : text,\n    null,\n    VNodeFlags.Text,\n    key,\n    null,\n    null,\n    null,\n  ) as VNode;\n}\n\nexport function createFragment(\n  children: any,\n  childFlags: ChildFlags,\n  key?: string | number | null,\n): VNode {\n  const fragment = createVNode(\n    VNodeFlags.Fragment,\n    VNodeFlags.Fragment as any,\n    null,\n    children,\n    childFlags,\n    null,\n    key,\n    null,\n  );\n\n  switch (fragment.childFlags) {\n    case ChildFlags.HasInvalidChildren:\n      fragment.children = createVoidVNode();\n      fragment.childFlags = ChildFlags.HasVNodeChildren;\n      break;\n    case ChildFlags.HasTextChildren:\n      fragment.children = [createTextVNode(children)];\n      fragment.childFlags = ChildFlags.HasNonKeyedChildren;\n      break;\n    default:\n      break;\n  }\n\n  return fragment;\n}\n\nexport function normalizeProps(vNode: VNode): VNode {\n  const props = vNode.props;\n\n  if (props) {\n    const flags = vNode.flags;\n\n    if (flags & VNodeFlags.Element) {\n      if (props.children !== void 0 && isNullOrUndef(vNode.children)) {\n        normalizeChildren(vNode, props.children);\n      }\n      if (props.className !== void 0) {\n        if (isNullOrUndef(vNode.className)) {\n          vNode.className = props.className || null;\n        }\n        props.className = undefined;\n      }\n    }\n    if (props.key !== void 0) {\n      vNode.key = props.key;\n      props.key = undefined;\n    }\n    if (props.ref !== void 0) {\n      if (flags & VNodeFlags.ComponentFunction) {\n        vNode.ref = { ...vNode.ref, ...props.ref };\n      } else {\n        vNode.ref = props.ref;\n      }\n\n      props.ref = undefined;\n    }\n  }\n\n  return vNode;\n}\n\n/*\n * Fragment is different from normal vNode,\n * because when it needs to be cloned we need to clone its children too\n * But not normalize, because otherwise those possibly get KEY and re-mount\n */\nfunction cloneFragment(vNodeToClone: VNode): VNode {\n  const oldChildren = vNodeToClone.children;\n  const childFlags = vNodeToClone.childFlags;\n\n  return createFragment(\n    childFlags === ChildFlags.HasVNodeChildren\n      ? directClone(oldChildren as VNode)\n      : (oldChildren as VNode[]).map(directClone),\n    childFlags,\n    vNodeToClone.key,\n  );\n}\n\nexport function directClone(vNodeToClone: VNode): VNode {\n  const flags = vNodeToClone.flags & VNodeFlags.ClearInUse;\n  let props = vNodeToClone.props;\n\n  if (flags & VNodeFlags.Component) {\n    if (!isNull(props)) {\n      const propsToClone = props;\n      props = {};\n      for (const key in propsToClone) {\n        props[key] = propsToClone[key];\n      }\n    }\n  }\n  if ((flags & VNodeFlags.Fragment) === 0) {\n    return new V(\n      vNodeToClone.childFlags,\n      vNodeToClone.children,\n      vNodeToClone.className,\n      flags,\n      vNodeToClone.key,\n      props,\n      vNodeToClone.ref,\n      vNodeToClone.type,\n    ) as VNode;\n  }\n\n  return cloneFragment(vNodeToClone);\n}\n\nexport function createVoidVNode(): VNode {\n  return createTextVNode('', null);\n}\n\nexport function createPortal(children, container: ParentDOM): VNode {\n  const normalizedRoot = normalizeRoot(children);\n\n  return createVNode(\n    VNodeFlags.Portal,\n    VNodeFlags.Portal as any,\n    null,\n    normalizedRoot,\n    ChildFlags.UnknownChildren,\n    null,\n    normalizedRoot.key,\n    container as any, // Should there be own prop for this?\n  );\n}\n\nexport function _normalizeVNodes(\n  nodes: any[],\n  result: VNode[],\n  index: number,\n  currentKey: string,\n): void {\n  for (const len = nodes.length; index < len; index++) {\n    let n = nodes[index];\n\n    if (!isInvalid(n)) {\n      const newKey: string = currentKey + keyPrefix + index;\n\n      if (isArray(n)) {\n        _normalizeVNodes(n, result, 0, newKey);\n      } else {\n        if (isStringOrNumber(n)) {\n          n = createTextVNode(n, newKey);\n        } else {\n          if (process.env.NODE_ENV !== 'production') {\n            throwIfObjectIsNotVNode(n);\n          }\n          const oldKey = n.key;\n          const isPrefixedKey = isString(oldKey) && oldKey[0] === keyPrefix;\n\n          if (n.flags & VNodeFlags.InUseOrNormalized || isPrefixedKey) {\n            n = directClone(n);\n          }\n\n          n.flags |= VNodeFlags.Normalized;\n\n          if (!isPrefixedKey) {\n            if (isNull(oldKey)) {\n              n.key = newKey;\n            } else {\n              n.key = currentKey + oldKey;\n            }\n          } else if (oldKey.substring(0, currentKey.length) !== currentKey) {\n            n.key = currentKey + oldKey;\n          }\n        }\n\n        result.push(n);\n      }\n    }\n  }\n}\n\nexport function getFlagsForElementVnode(type: string): VNodeFlags {\n  switch (type) {\n    case 'svg':\n      return VNodeFlags.SvgElement;\n    case 'input':\n      return VNodeFlags.InputElement;\n    case 'select':\n      return VNodeFlags.SelectElement;\n    case 'textarea':\n      return VNodeFlags.TextareaElement;\n    // @ts-expect-error Fragment is special case\n    case Fragment:\n      return VNodeFlags.Fragment;\n    default:\n      return VNodeFlags.HtmlElement;\n  }\n}\n\nexport function normalizeChildren(vNode: VNode, children): VNode {\n  let newChildren;\n  let newChildFlags: ChildFlags = ChildFlags.HasInvalidChildren;\n\n  // Don't change children to match strict equal (===) true in patching\n  if (isInvalid(children)) {\n    newChildren = children;\n  } else if (isStringOrNumber(children)) {\n    newChildFlags = ChildFlags.HasTextChildren;\n    newChildren = children;\n  } else if (isArray(children)) {\n    const len = children.length;\n\n    for (let i = 0; i < len; ++i) {\n      let n = children[i];\n\n      if (isInvalid(n) || isArray(n)) {\n        newChildren = newChildren || children.slice(0, i);\n\n        _normalizeVNodes(children, newChildren, i, '');\n        break;\n      } else if (isStringOrNumber(n)) {\n        newChildren = newChildren || children.slice(0, i);\n        newChildren.push(createTextVNode(n, keyPrefix + i));\n      } else {\n        if (process.env.NODE_ENV !== 'production') {\n          throwIfObjectIsNotVNode(n);\n        }\n        const key = n.key;\n        const needsCloning: boolean =\n          (n.flags & VNodeFlags.InUseOrNormalized) > 0;\n        const isNullKey: boolean = isNull(key);\n        const isPrefixed: boolean = isString(key) && key[0] === keyPrefix;\n\n        if (needsCloning || isNullKey || isPrefixed) {\n          newChildren = newChildren || children.slice(0, i);\n          if (needsCloning || isPrefixed) {\n            n = directClone(n);\n          }\n          if (isNullKey || isPrefixed) {\n            n.key = keyPrefix + i;\n          }\n          newChildren.push(n);\n        } else if (newChildren) {\n          newChildren.push(n);\n        }\n\n        n.flags |= VNodeFlags.Normalized;\n      }\n    }\n    newChildren = newChildren || children;\n    if (newChildren.length === 0) {\n      newChildFlags = ChildFlags.HasInvalidChildren;\n    } else {\n      newChildFlags = ChildFlags.HasKeyedChildren;\n    }\n  } else {\n    newChildren = children;\n    newChildren.flags |= VNodeFlags.Normalized;\n\n    if (children.flags & VNodeFlags.InUseOrNormalized) {\n      newChildren = directClone(children as VNode);\n    }\n    newChildFlags = ChildFlags.HasVNodeChildren;\n  }\n\n  vNode.children = newChildren;\n  vNode.childFlags = newChildFlags;\n\n  return vNode;\n}\n\nexport function normalizeRoot(input): VNode {\n  if (isInvalid(input) || isStringOrNumber(input)) {\n    return createTextVNode(input, null);\n  }\n  if (isArray(input)) {\n    return createFragment(input, ChildFlags.UnknownChildren, null);\n  }\n\n  return input.flags & VNodeFlags.InUse ? directClone(input) : input;\n}\n"
  },
  {
    "path": "packages/inferno/src/core/nativetypes.ts",
    "content": "// These types need to be in another file to not conflict with Inferno event type names\nexport type NativeClipboardEvent = ClipboardEvent;\nexport type NativeCompositionEvent = CompositionEvent;\nexport type NativeDragEvent = DragEvent;\nexport type NativeFocusEvent = FocusEvent;\n"
  },
  {
    "path": "packages/inferno/src/core/refs.ts",
    "content": "import { isFunction, isNullOrUndef, warning } from 'inferno-shared';\nimport { safeCall1 } from '../DOM/utils/common';\nimport type { InfernoNode, Props, RefObject } from './types';\n\nexport function createRef<T = Element>(): RefObject<T> {\n  return {\n    current: null,\n  };\n}\n\n// TODO: Make this return value typed\nexport function forwardRef<T = any, P = Props<any>>(\n  render: (\n    props: Readonly<{ children?: InfernoNode }> & Readonly<P>,\n    ref: RefObject<T>,\n  ) => InfernoNode,\n): any {\n  if (process.env.NODE_ENV !== 'production') {\n    if (!isFunction(render)) {\n      warning(\n        `forwardRef requires a render function but was given ${\n          render === null ? 'null' : typeof render\n        }.`,\n      );\n\n      return;\n    }\n  }\n\n  return {\n    render,\n  };\n}\n\nexport function unmountRef(ref): void {\n  if (!isNullOrUndef(ref)) {\n    if (!safeCall1(ref, null) && (ref as RefObject<unknown>).current) {\n      ref.current = null;\n    }\n  }\n}\n\nexport function mountRef(ref, value, lifecycle: Array<() => void>): void {\n  if (!isNullOrUndef(ref) && (isFunction(ref) || ref.current !== void 0)) {\n    lifecycle.push(() => {\n      if (!safeCall1(ref, value) && ref.current !== void 0) {\n        ref.current = value;\n      }\n    });\n  }\n}\n"
  },
  {
    "path": "packages/inferno/src/core/types.ts",
    "content": "/* eslint-disable */\nimport type {\n  NativeClipboardEvent,\n  NativeCompositionEvent,\n  NativeDragEvent,\n  NativeFocusEvent,\n} from './nativetypes';\nimport type { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport type { PropertiesHyphen } from 'csstype';\n\nexport interface LinkedEvent<T, E extends Event> {\n  data: T;\n  event: (data: T, event: E) => void;\n}\n\nexport type InfernoText = string | number;\nexport type InfernoChild = Inferno.InfernoElement | InfernoText;\n\ninterface InfernoNodeArray extends Array<InfernoNode> {}\n\nexport type InfernoFragment = {} | InfernoNodeArray;\nexport type InfernoSingleNode = InfernoChild | boolean | null | undefined;\nexport type InfernoNode = InfernoSingleNode | InfernoFragment;\nexport type InfernoKeyedNode = Inferno.InfernoElement & { key: string | number };\nexport type NonEmptyProps = Record<string, unknown>;\nexport type ContextObject = Record<string, unknown>;\nexport type ParentDOM =\n  | Element\n  | SVGAElement\n  | ShadowRoot\n  | DocumentFragment\n  | HTMLElement\n  | Node\n  | null;\n\n// IComponent is defined here, instead of Component to de-couple implementation from interface\nexport interface IComponent<P, S> {\n  // Public\n  state: S | null;\n  props: Readonly<\n    {\n      children?: InfernoNode;\n    } & P\n  >;\n  context?: any;\n  displayName?: string;\n  refs?: any;\n\n  forceUpdate(callback?: Function);\n\n  setState<K extends keyof S>(\n    newState:\n      | ((\n          prevState: Readonly<S>,\n          props: Readonly<{ children?: InfernoNode } & P>,\n        ) => Pick<S, K> | S | null)\n      | (Pick<S, K> | S | null),\n    callback?: () => void,\n  ): void;\n\n  componentDidMount?(): void;\n\n  componentWillMount?(): void;\n\n  componentWillReceiveProps?(\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n    nextContext: any,\n  ): void;\n\n  shouldComponentUpdate?(\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n    nextState: Readonly<S>,\n    context: any,\n  ): boolean;\n\n  componentWillUpdate?(\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n    nextState: Readonly<S>,\n    context: any,\n  ): void;\n\n  componentDidUpdate?(\n    prevProps: Readonly<{ children?: InfernoNode } & P>,\n    prevState: Readonly<S>,\n    snapshot: any,\n  ): void;\n\n  componentWillUnmount?(): void;\n\n  componentDidAppear?(domNode: Element): void;\n\n  componentWillDisappear?(domNode: Element, callback: Function): void;\n\n  componentWillMove?(\n    parentVNode: VNode,\n    parentDOM: Element,\n    dom: Element,\n  ): void;\n\n  getChildContext?(): void;\n\n  getSnapshotBeforeUpdate?(\n    prevProps: Readonly<{ children?: InfernoNode } & P>,\n    prevState: Readonly<S>,\n  ): any;\n\n  render(\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n    nextState: Readonly<S>,\n    nextContext: any,\n  ): InfernoNode;\n}\n\nexport interface SemiSyntheticEvent<T> extends Event {\n  /**\n   * A reference to the element on which the event listener is registered.\n   */\n  currentTarget: EventTarget & T;\n  isDefaultPrevented?: () => boolean;\n  isPropagationStopped?: () => boolean;\n}\n\nexport type ClipboardEvent<T> = SemiSyntheticEvent<T> & NativeClipboardEvent;\nexport type CompositionEvent<T> = SemiSyntheticEvent<T> &\n  NativeCompositionEvent;\nexport type DragEvent<T> = InfernoMouseEvent<T> & NativeDragEvent;\nexport type FocusEvent<T> = SemiSyntheticEvent<T> & NativeFocusEvent;\nexport interface FormEvent<T> extends SemiSyntheticEvent<T> {\n  target: EventTarget & T;\n}\n\nexport interface ChangeEvent<T> extends SemiSyntheticEvent<T> {\n  target: EventTarget & T;\n}\n\nexport type InfernoKeyboardEvent<T> = SemiSyntheticEvent<T> & KeyboardEvent;\nexport type InfernoMouseEvent<T> = SemiSyntheticEvent<T> &\n  MouseEvent & {\n    target: EventTarget & T;\n  };\nexport type InfernoTouchEvent<T> = SemiSyntheticEvent<T> & TouchEvent;\nexport type InfernoPointerEvent<T> = SemiSyntheticEvent<T> & PointerEvent;\nexport type InfernoUIEvent<T> = SemiSyntheticEvent<T> & UIEvent;\nexport type InfernoWheelEvent<T> = InfernoMouseEvent<T> & WheelEvent;\nexport type InfernoAnimationEvent<T> = SemiSyntheticEvent<T> & AnimationEvent;\nexport type InfernoTransitionEvent<T> = SemiSyntheticEvent<T> & TransitionEvent;\ntype Booleanish = boolean | 'true' | 'false';\n\n//\n// Event Handler Types\n// ----------------------------------------------------------------------\n\nexport type EventHandler<E extends SemiSyntheticEvent<any>> =\n  | { bivarianceHack(event: E): void }['bivarianceHack']\n  | LinkedEvent<any, E>\n  | null;\n\nexport type InfernoEventHandler<T = Element> = EventHandler<\n  SemiSyntheticEvent<T>\n>;\n\nexport type ClipboardEventHandler<T = Element> = EventHandler<\n  ClipboardEvent<T>\n>;\nexport type CompositionEventHandler<T = Element> = EventHandler<\n  CompositionEvent<T>\n>;\nexport type DragEventHandler<T = Element> = EventHandler<DragEvent<T>>;\nexport type FocusEventHandler<T = Element> = EventHandler<FocusEvent<T>>;\nexport type FormEventHandler<T = Element> = EventHandler<FormEvent<T>>;\nexport type ChangeEventHandler<T = Element> = EventHandler<ChangeEvent<T>>;\nexport type KeyboardEventHandler<T = Element> = EventHandler<\n  InfernoKeyboardEvent<T>\n>;\nexport type MouseEventHandler<T = Element> = EventHandler<InfernoMouseEvent<T>>;\nexport type TouchEventHandler<T = Element> = EventHandler<InfernoTouchEvent<T>>;\nexport type PointerEventHandler<T = Element> = EventHandler<\n  InfernoPointerEvent<T>\n>;\nexport type UIEventHandler<T = Element> = EventHandler<InfernoUIEvent<T>>;\nexport type WheelEventHandler<T = Element> = EventHandler<InfernoWheelEvent<T>>;\nexport type AnimationEventHandler<T = Element> = EventHandler<\n  InfernoAnimationEvent<T>\n>;\nexport type TransitionEventHandler<T = Element> = EventHandler<\n  InfernoTransitionEvent<T>\n>;\n\nexport type Key = string | number | undefined | null;\n\ntype CrossOrigin = 'anonymous' | 'use-credentials' | '' | null | undefined;\n\nexport interface VNode {\n  children: InfernoNode;\n  childFlags: ChildFlags;\n  dom: Element | null;\n  className: string | null | undefined;\n  flags: VNodeFlags;\n  isValidated?: boolean;\n  key: Key;\n  props: any;\n  ref: any;\n  type: any;\n}\n\nexport interface RefObject<T> {\n  readonly current: T | null;\n}\n\nexport type Ref<T = Element> = {\n  bivarianceHack(instance: T | null): any;\n}['bivarianceHack'];\n\nexport interface ForwardRef<P, T> extends Inferno.StatelessComponent<P> {\n  ref: Ref<T>;\n}\n\nexport interface Refs<P> {\n  onComponentDidMount?: (\n    domNode: Element | null,\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n  ) => void;\n\n  onComponentWillMount?(props: Readonly<{ children?: InfernoNode } & P>): void;\n\n  onComponentShouldUpdate?(\n    lastProps: Readonly<{ children?: InfernoNode } & P>,\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n  ): boolean;\n\n  onComponentWillUpdate?(\n    lastProps: Readonly<{ children?: InfernoNode } & P>,\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n  ): void;\n\n  onComponentDidUpdate?(\n    lastProps: Readonly<{ children?: InfernoNode } & P>,\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n  ): void;\n\n  onComponentWillUnmount?(\n    domNode: Element,\n    nextProps: Readonly<{ children?: InfernoNode } & P>,\n  ): void;\n\n  onComponentDidAppear?(\n    domNode: Element,\n    props: Readonly<{ children?: InfernoNode } & P>,\n  ): void;\n\n  onComponentWillDisappear?(\n    domNode: Element,\n    props: Readonly<{ children?: InfernoNode } & P>,\n    callback: Function,\n  ): void;\n\n  onComponentWillMove?(\n    parentVNode: VNode,\n    parentDOM: Element,\n    dom: Element,\n    props: Readonly<{ children?: InfernoNode } & P>,\n  ): void;\n}\n\nexport interface Props<T> {\n  children?: InfernoNode;\n  key?: Key;\n  ref?: Ref<T> | undefined;\n}\n\nexport declare namespace Inferno {\n  //\n  // Inferno Elements\n  // ----------------------------------------------------------------------\n  // tslint:disable-next-line:interface-over-type-literal\n  type ComponentState = {};\n  type ExoticComponent<P = {}> = (props: P) => InfernoElement;\n\n  interface Attributes {\n    key?: Key;\n\n    $ReCreate?: boolean;\n    $HasVNodeChildren?: boolean;\n    $HasNonKeyedChildren?: boolean;\n    $HasKeyedChildren?: boolean;\n    $HasTextChildren?: boolean;\n    $ChildFlag?: number;\n  }\n  interface ClassAttributes<T> extends Attributes {\n    ref?: Ref<T> | RefObject<T> | null | undefined;\n  }\n\n  interface InfernoElement<P = any> {\n    type: string | ComponentClass<P> | SFC<P>;\n    props: P;\n    key?: Key;\n  }\n\n  interface SFCElement<P> extends InfernoElement<P> {\n    type: SFC<P>;\n  }\n\n  type CElement<P, T extends IComponent<P, ComponentState>> = ComponentElement<\n    P,\n    T\n  >;\n  interface ComponentElement<P, T extends IComponent<P, ComponentState>>\n    extends InfernoElement<P> {\n    type: ComponentClass<P>;\n    ref?: Ref<T> | undefined;\n  }\n\n  // string fallback for custom web-components\n  interface DOMElement<\n    P extends HTMLAttributes<T> | SVGAttributes<T>,\n    T extends Element,\n  > extends InfernoElement<P> {\n    type: string;\n    ref: Ref<T>;\n  }\n\n  // InfernoHTML for InfernoHTMLElement\n  interface InfernoHTMLElement<T extends HTMLElement>\n    extends DetailedInfernoHTMLElement<AllHTMLAttributes<T>, T> {}\n\n  interface DetailedInfernoHTMLElement<\n    P extends HTMLAttributes<T>,\n    T extends HTMLElement,\n  > extends DOMElement<P, T> {\n    type: keyof InfernoHTML;\n  }\n\n  // InfernoSVG for InfernoSVGElement\n  interface InfernoSVGElement\n    extends DOMElement<SVGAttributes<SVGElement>, SVGElement> {\n    type: keyof InfernoSVG;\n  }\n\n  //\n  // Factories\n  // ----------------------------------------------------------------------\n\n  type Factory<P> = (\n    props?: Attributes & P,\n    ...children: InfernoNode[]\n  ) => InfernoElement<P>;\n\n  type SFCFactory<P> = (\n    props?: Attributes & P,\n    ...children: InfernoNode[]\n  ) => SFCElement<P>;\n\n  type ComponentFactory<P, T extends IComponent<P, ComponentState>> = (\n    props?: ClassAttributes<T> & P,\n    ...children: InfernoNode[]\n  ) => CElement<P, T>;\n\n  type CFactory<P, T extends IComponent<P, ComponentState>> = ComponentFactory<\n    P,\n    T\n  >;\n\n  type DOMFactory<P extends DOMAttributes<T>, T extends Element> = (\n    props?: (ClassAttributes<T> & P) | null,\n    ...children: InfernoNode[]\n  ) => DOMElement<P, T>;\n\n  interface HTMLFactory<T extends HTMLElement>\n    extends DetailedHTMLFactory<AllHTMLAttributes<T>, T> {}\n\n  interface DetailedHTMLFactory<\n    P extends HTMLAttributes<T>,\n    T extends HTMLElement,\n  > extends DOMFactory<P, T> {\n    (\n      props?: (ClassAttributes<T> & P) | null,\n      ...children: InfernoNode[]\n    ): DetailedInfernoHTMLElement<P, T>;\n  }\n\n  interface SVGFactory\n    extends DOMFactory<SVGAttributes<SVGElement>, SVGElement> {\n    (\n      props?: (ClassAttributes<SVGElement> & SVGAttributes<SVGElement>) | null,\n      ...children: InfernoNode[]\n    ): InfernoSVGElement;\n  }\n\n  //\n  // Inferno Nodes\n  // ----------------------------------------------------------------------\n\n  const version: string;\n\n  //\n  // Component API\n  // ----------------------------------------------------------------------\n\n  interface ChildContextProvider<CC> {\n    getChildContext(): CC;\n  }\n\n  //\n  // Class Interfaces\n  // ----------------------------------------------------------------------\n\n  type SFC<P = {}> = StatelessComponent<P>;\n  interface StatelessComponent<P = {}> {\n    (\n      props: {\n        children?: InfernoNode;\n      } & P &\n        Refs<P>,\n      context?: any,\n    ): InfernoElement | null;\n    defaultProps?: Partial<P> | undefined | null;\n    defaultHooks?: Refs<P> | undefined | null;\n  }\n\n  interface ComponentClass<P = {}> {\n    new (\n      props?: {\n        children?: InfernoNode;\n      } & P,\n      context?: any,\n    ): IComponent<P, ComponentState>;\n    defaultProps?: Partial<P> | undefined | null;\n  }\n\n  //\n  // Props / DOM Attributes\n  // ----------------------------------------------------------------------\n\n  interface HTMLProps<T> extends AllHTMLAttributes<T>, ClassAttributes<T> {}\n\n  type DetailedHTMLProps<E extends HTMLAttributes<T>, T> = ClassAttributes<T> &\n    E;\n\n  interface SVGProps<T> extends SVGAttributes<T>, ClassAttributes<T> {}\n\n  interface DOMAttributes<T> {\n    children?: InfernoNode;\n    dangerouslySetInnerHTML?:\n      | {\n          __html: string;\n        }\n      | null\n      | undefined;\n\n    // Clipboard Events\n    onCopy?: ClipboardEventHandler<T> | undefined;\n    onCut?: ClipboardEventHandler<T> | undefined;\n    onPaste?: ClipboardEventHandler<T> | undefined;\n\n    // Composition Events\n    onCompositionEnd?: CompositionEventHandler<T> | undefined;\n    onCompositionStart?: CompositionEventHandler<T> | undefined;\n    onCompositionUpdate?: CompositionEventHandler<T> | undefined;\n\n    // Focus Events\n    onFocus?: FocusEventHandler<T> | undefined;\n    onBlur?: FocusEventHandler<T> | undefined;\n\n    // Form Events\n    onChange?: FormEventHandler<T> | undefined | null;\n    onBeforeInput?: FormEventHandler<T> | undefined;\n    onInput?: FormEventHandler<T> | undefined;\n    onReset?: FormEventHandler<T> | undefined;\n    onSubmit?: FormEventHandler<T> | undefined;\n    onInvalid?: FormEventHandler<T> | undefined;\n\n    // Image Events\n    onLoad?: InfernoEventHandler<T> | undefined;\n    onError?: InfernoEventHandler<T> | undefined; // also a Media Event\n\n    // Keyboard Events\n    onKeyDown?: KeyboardEventHandler<T> | undefined;\n    onKeyPress?: KeyboardEventHandler<T> | undefined;\n    onKeyUp?: KeyboardEventHandler<T> | undefined;\n\n    // Media Events\n    onAbort?: InfernoEventHandler<T> | undefined;\n    onCanPlay?: InfernoEventHandler<T> | undefined;\n    onCanPlayThrough?: InfernoEventHandler<T> | undefined;\n    onDurationChange?: InfernoEventHandler<T> | undefined;\n    onEmptied?: InfernoEventHandler<T> | undefined;\n    onEncrypted?: InfernoEventHandler<T> | undefined;\n    onEnded?: InfernoEventHandler<T> | undefined;\n    onLoadedData?: InfernoEventHandler<T> | undefined;\n    onLoadedMetadata?: InfernoEventHandler<T> | undefined;\n    onLoadStart?: InfernoEventHandler<T> | undefined;\n    onPause?: InfernoEventHandler<T> | undefined;\n    onPlay?: InfernoEventHandler<T> | undefined;\n    onPlaying?: InfernoEventHandler<T> | undefined;\n    onProgress?: InfernoEventHandler<T> | undefined;\n    onRateChange?: InfernoEventHandler<T> | undefined;\n    onSeeked?: InfernoEventHandler<T> | undefined;\n    onSeeking?: InfernoEventHandler<T> | undefined;\n    onStalled?: InfernoEventHandler<T> | undefined;\n    onSuspend?: InfernoEventHandler<T> | undefined;\n    onTimeUpdate?: InfernoEventHandler<T> | undefined;\n    onVolumeChange?: InfernoEventHandler<T> | undefined;\n    onWaiting?: InfernoEventHandler<T> | undefined;\n\n    // MouseEvents\n    onAuxClick?: MouseEventHandler<T> | undefined;\n    onClick?: MouseEventHandler<T> | undefined;\n    onContextMenu?: MouseEventHandler<T> | undefined;\n    onDblClick?: MouseEventHandler<T> | undefined;\n    onDrag?: DragEventHandler<T> | undefined;\n    onDragEnd?: DragEventHandler<T> | undefined;\n    onDragEnter?: DragEventHandler<T> | undefined;\n    onDragExit?: DragEventHandler<T> | undefined;\n    onDragLeave?: DragEventHandler<T> | undefined;\n    onDragOver?: DragEventHandler<T> | undefined;\n    onDragStart?: DragEventHandler<T> | undefined;\n    onDrop?: DragEventHandler<T> | undefined;\n    onMouseDown?: MouseEventHandler<T> | undefined;\n    onMouseEnter?: MouseEventHandler<T> | undefined;\n    onMouseLeave?: MouseEventHandler<T> | undefined;\n    onMouseMove?: MouseEventHandler<T> | undefined;\n    onMouseOut?: MouseEventHandler<T> | undefined;\n    onMouseOver?: MouseEventHandler<T> | undefined;\n    onMouseUp?: MouseEventHandler<T> | undefined;\n\n    // Selection Events\n    onSelect?: InfernoEventHandler<T> | undefined;\n\n    // Touch Events\n    onTouchCancel?: TouchEventHandler<T> | undefined;\n    onTouchEnd?: TouchEventHandler<T> | undefined;\n    onTouchMove?: TouchEventHandler<T> | undefined;\n    onTouchStart?: TouchEventHandler<T> | undefined;\n\n    // Pointer Events\n    onPointerDown?: PointerEventHandler<T> | undefined;\n    onPointerMove?: PointerEventHandler<T> | undefined;\n    onPointerUp?: PointerEventHandler<T> | undefined;\n    onPointerCancel?: PointerEventHandler<T> | undefined;\n    onPointerEnter?: PointerEventHandler<T> | undefined;\n    onPointerLeave?: PointerEventHandler<T> | undefined;\n    onPointerOver?: PointerEventHandler<T> | undefined;\n    onPointerOut?: PointerEventHandler<T> | undefined;\n\n    // UI Events\n    onScroll?: UIEventHandler<T> | undefined;\n\n    // Wheel Events\n    onWheel?: WheelEventHandler<T> | undefined;\n\n    // Animation Events\n    onAnimationStart?: AnimationEventHandler<T> | undefined;\n    onAnimationEnd?: AnimationEventHandler<T> | undefined;\n    onAnimationIteration?: AnimationEventHandler<T> | undefined;\n\n    // Transition Events\n    onTransitionEnd?: TransitionEventHandler<T> | undefined;\n\n    // NATIVE EVENTS\n    // Clipboard Events\n    oncopy?: ClipboardEventHandler<T> | undefined;\n    oncut?: ClipboardEventHandler<T> | undefined;\n    onpaste?: ClipboardEventHandler<T> | undefined;\n\n    // Composition Events\n    oncompositionend?: CompositionEventHandler<T> | undefined;\n    oncompositionstart?: CompositionEventHandler<T> | undefined;\n    oncompositionupdate?: CompositionEventHandler<T> | undefined;\n\n    // Focus Events\n    onfocus?: FocusEventHandler<T> | undefined;\n    onblur?: FocusEventHandler<T> | undefined;\n\n    // Form Events\n    onchange?: FormEventHandler<T> | undefined | null;\n    onbeforeinput?: FormEventHandler<T> | undefined;\n    oninput?: FormEventHandler<T> | undefined;\n    onreset?: FormEventHandler<T> | undefined;\n    onsubmit?: FormEventHandler<T> | undefined;\n    oninvalid?: FormEventHandler<T> | undefined;\n\n    // Image Events\n    onload?: InfernoEventHandler<T> | undefined;\n    onerror?: InfernoEventHandler<T> | undefined; // also a Media Event\n\n    // Keyboard Events\n    onkeydown?: KeyboardEventHandler<T> | undefined;\n    onkeypress?: KeyboardEventHandler<T> | undefined;\n    onkeyup?: KeyboardEventHandler<T> | undefined;\n\n    // Media Events\n    onabort?: InfernoEventHandler<T> | undefined;\n    oncanplay?: InfernoEventHandler<T> | undefined;\n    oncanplaythrough?: InfernoEventHandler<T> | undefined;\n    ondurationchange?: InfernoEventHandler<T> | undefined;\n    onemptied?: InfernoEventHandler<T> | undefined;\n    onencrypted?: InfernoEventHandler<T> | undefined;\n    onended?: InfernoEventHandler<T> | undefined;\n    onloadeddata?: InfernoEventHandler<T> | undefined;\n    onloadedmetadata?: InfernoEventHandler<T> | undefined;\n    onloadstart?: InfernoEventHandler<T> | undefined;\n    onpause?: InfernoEventHandler<T> | undefined;\n    onplay?: InfernoEventHandler<T> | undefined;\n    onplaying?: InfernoEventHandler<T> | undefined;\n    onprogress?: InfernoEventHandler<T> | undefined;\n    onratechange?: InfernoEventHandler<T> | undefined;\n    onseeked?: InfernoEventHandler<T> | undefined;\n    onseeking?: InfernoEventHandler<T> | undefined;\n    onstalled?: InfernoEventHandler<T> | undefined;\n    onsuspend?: InfernoEventHandler<T> | undefined;\n    ontimeupdate?: InfernoEventHandler<T> | undefined;\n    onvolumechange?: InfernoEventHandler<T> | undefined;\n    onwaiting?: InfernoEventHandler<T> | undefined;\n\n    // MouseEvents\n    onauxclick?: MouseEventHandler<T> | undefined;\n    onclick?: MouseEventHandler<T> | undefined;\n    oncontextmenu?: MouseEventHandler<T> | undefined;\n    ondblclick?: MouseEventHandler<T> | undefined;\n    ondrag?: DragEventHandler<T> | undefined;\n    ondragend?: DragEventHandler<T> | undefined;\n    ondragenter?: DragEventHandler<T> | undefined;\n    ondragexit?: DragEventHandler<T> | undefined;\n    ondragLeave?: DragEventHandler<T> | undefined;\n    ondragover?: DragEventHandler<T> | undefined;\n    ondragstart?: DragEventHandler<T> | undefined;\n    ondrop?: DragEventHandler<T> | undefined;\n    onmousedown?: MouseEventHandler<T> | undefined;\n    onmouseenter?: MouseEventHandler<T> | undefined;\n    onmouseleave?: MouseEventHandler<T> | undefined;\n    onmousemove?: MouseEventHandler<T> | undefined;\n    onmouseout?: MouseEventHandler<T> | undefined;\n    onmouseover?: MouseEventHandler<T> | undefined;\n    onmouseup?: MouseEventHandler<T> | undefined;\n\n    // Selection Events\n    onselect?: InfernoEventHandler<T> | undefined;\n\n    // Touch Events\n    ontouchcancel?: TouchEventHandler<T> | undefined;\n    ontouchend?: TouchEventHandler<T> | undefined;\n    ontouchmove?: TouchEventHandler<T> | undefined;\n    ontouchstart?: TouchEventHandler<T> | undefined;\n\n    // Pointer Events\n    onpointerdown?: PointerEventHandler<T> | undefined;\n    onpointermove?: PointerEventHandler<T> | undefined;\n    onpointerup?: PointerEventHandler<T> | undefined;\n    onpointercancel?: PointerEventHandler<T> | undefined;\n    onpointerenter?: PointerEventHandler<T> | undefined;\n    onpointerleave?: PointerEventHandler<T> | undefined;\n    onpointerover?: PointerEventHandler<T> | undefined;\n    onpointerout?: PointerEventHandler<T> | undefined;\n\n    // UI Events\n    onscroll?: UIEventHandler<T> | undefined;\n\n    // Wheel Events\n    onwheel?: WheelEventHandler<T> | undefined;\n\n    // Animation Events\n    onanimationstart?: AnimationEventHandler<T> | undefined;\n    onanimationend?: AnimationEventHandler<T> | undefined;\n    onanimationiteration?: AnimationEventHandler<T> | undefined;\n\n    // Transition Events\n    ontransitionend?: TransitionEventHandler<T> | undefined;\n  }\n\n  // All the WAI-ARIA 1.1 attributes from https://www.w3.org/TR/wai-aria-1.1/\n  // All the WAI-ARIA 1.1 attributes from https://www.w3.org/TR/wai-aria-1.1/\n  interface AriaAttributes {\n    /** Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. */\n    'aria-activedescendant'?: string | null | undefined;\n    /** Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute. */\n    'aria-atomic'?: Booleanish | null | undefined;\n    /**\n     * Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be\n     * presented if they are made.\n     */\n    'aria-autocomplete'?:\n      | 'none'\n      | 'inline'\n      | 'list'\n      | 'both'\n      | null\n      | undefined;\n    /** Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user. */\n    /**\n     * Defines a string value that labels the current element, which is intended to be converted into Braille.\n     * @see aria-label.\n     */\n    'aria-braillelabel'?: string | null | undefined;\n    /**\n     * Defines a human-readable, author-localized abbreviated description for the role of an element, which is intended to be converted into Braille.\n     * @see aria-roledescription.\n     */\n    'aria-brailleroledescription'?: string | null | undefined;\n    'aria-busy'?: Booleanish | null | undefined;\n    /**\n     * Indicates the current \"checked\" state of checkboxes, radio buttons, and other widgets.\n     * @see aria-pressed @see aria-selected.\n     */\n    'aria-checked'?: boolean | 'false' | 'mixed' | 'true' | null | undefined;\n    /**\n     * Defines the total number of columns in a table, grid, or treegrid.\n     * @see aria-colindex.\n     */\n    'aria-colcount'?: number | null | undefined;\n    /**\n     * Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid.\n     * @see aria-colcount @see aria-colspan.\n     */\n    'aria-colindex'?: number | null | undefined;\n    /**\n     * Defines a human readable text alternative of aria-colindex.\n     * @see aria-rowindextext.\n     */\n    'aria-colindextext'?: string | null | undefined;\n    /**\n     * Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid.\n     * @see aria-colindex @see aria-rowspan.\n     */\n    'aria-colspan'?: number | null | undefined;\n    /**\n     * Identifies the element (or elements) whose contents or presence are controlled by the current element.\n     * @see aria-owns.\n     */\n    'aria-controls'?: string | null | undefined;\n    /** Indicates the element that represents the current item within a container or set of related elements. */\n    'aria-current'?:\n      | boolean\n      | 'false'\n      | 'true'\n      | 'page'\n      | 'step'\n      | 'location'\n      | 'date'\n      | 'time'\n      | null\n      | undefined;\n    /**\n     * Identifies the element (or elements) that describes the object.\n     * @see aria-labelledby\n     */\n    'aria-describedby'?: string | null | undefined;\n    /**\n     * Defines a string value that describes or annotates the current element.\n     * @see related aria-describedby.\n     */\n    'aria-description'?: string | null | undefined;\n    /**\n     * Identifies the element that provides a detailed, extended description for the object.\n     * @see aria-describedby.\n     */\n    'aria-details'?: string | null | undefined;\n    /**\n     * Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable.\n     * @see aria-hidden @see aria-readonly.\n     */\n    'aria-disabled'?: Booleanish | null | undefined;\n    /**\n     * Indicates what functions can be performed when a dragged object is released on the drop target.\n     * @deprecated in ARIA 1.1\n     */\n    'aria-dropeffect'?:\n      | 'none'\n      | 'copy'\n      | 'execute'\n      | 'link'\n      | 'move'\n      | 'popup'\n      | null\n      | undefined;\n    /**\n     * Identifies the element that provides an error message for the object.\n     * @see aria-invalid @see aria-describedby.\n     */\n    'aria-errormessage'?: string | null | undefined;\n    /** Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. */\n    'aria-expanded'?: Booleanish | null | undefined;\n    /**\n     * Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion,\n     * allows assistive technology to override the general default of reading in document source order.\n     */\n    'aria-flowto'?: string | null | undefined;\n    /**\n     * Indicates an element's \"grabbed\" state in a drag-and-drop operation.\n     * @deprecated in ARIA 1.1\n     */\n    'aria-grabbed'?: Booleanish | null | undefined;\n    /** Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element. */\n    'aria-haspopup'?:\n      | boolean\n      | 'false'\n      | 'true'\n      | 'menu'\n      | 'listbox'\n      | 'tree'\n      | 'grid'\n      | 'dialog'\n      | null\n      | undefined;\n    /**\n     * Indicates whether the element is exposed to an accessibility API.\n     * @see aria-disabled.\n     */\n    'aria-hidden'?: Booleanish | null | undefined;\n    /**\n     * Indicates the entered value does not conform to the format expected by the application.\n     * @see aria-errormessage.\n     */\n    'aria-invalid'?:\n      | boolean\n      | 'false'\n      | 'true'\n      | 'grammar'\n      | 'spelling'\n      | null\n      | undefined;\n    /** Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. */\n    'aria-keyshortcuts'?: string | null | undefined;\n    /**\n     * Defines a string value that labels the current element.\n     * @see aria-labelledby.\n     */\n    'aria-label'?: string | null | undefined;\n    /**\n     * Identifies the element (or elements) that labels the current element.\n     * @see aria-describedby.\n     */\n    'aria-labelledby'?: string | null | undefined;\n    /** Defines the hierarchical level of an element within a structure. */\n    'aria-level'?: number | null | undefined;\n    /** Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region. */\n    'aria-live'?: 'off' | 'assertive' | 'polite' | null | undefined;\n    /** Indicates whether an element is modal when displayed. */\n    'aria-modal'?: Booleanish | null | undefined;\n    /** Indicates whether a text box accepts multiple lines of input or only a single line. */\n    'aria-multiline'?: Booleanish | null | undefined;\n    /** Indicates that the user may select more than one item from the current selectable descendants. */\n    'aria-multiselectable'?: Booleanish | null | undefined;\n    /** Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous. */\n    'aria-orientation'?: 'horizontal' | 'vertical' | null | undefined;\n    /**\n     * Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship\n     * between DOM elements where the DOM hierarchy cannot be used to represent the relationship.\n     * @see aria-controls.\n     */\n    'aria-owns'?: string | null | undefined;\n    /**\n     * Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value.\n     * A hint could be a sample value or a brief description of the expected format.\n     */\n    'aria-placeholder'?: string | null | undefined;\n    /**\n     * Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM.\n     * @see aria-setsize.\n     */\n    'aria-posinset'?: number | null | undefined;\n    /**\n     * Indicates the current \"pressed\" state of toggle buttons.\n     * @see aria-checked @see aria-selected.\n     */\n    'aria-pressed'?: boolean | 'false' | 'mixed' | 'true' | null | undefined;\n    /**\n     * Indicates that the element is not editable, but is otherwise operable.\n     * @see aria-disabled.\n     */\n    'aria-readonly'?: Booleanish | null | undefined;\n    /**\n     * Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified.\n     * @see aria-atomic.\n     */\n    'aria-relevant'?:\n      | 'additions'\n      | 'additions removals'\n      | 'additions text'\n      | 'all'\n      | 'removals'\n      | 'removals additions'\n      | 'removals text'\n      | 'text'\n      | 'text additions'\n      | 'text removals'\n      | null\n      | undefined;\n    /** Indicates that user input is required on the element before a form may be submitted. */\n    'aria-required'?: Booleanish | null | undefined;\n    /** Defines a human-readable, author-localized description for the role of an element. */\n    'aria-roledescription'?: string | null | undefined;\n    /**\n     * Defines the total number of rows in a table, grid, or treegrid.\n     * @see aria-rowindex.\n     */\n    'aria-rowcount'?: number | null | undefined;\n    /**\n     * Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid.\n     * @see aria-rowcount @see aria-rowspan.\n     */\n    'aria-rowindex'?: number | null | undefined;\n    /**\n     * Defines a human readable text alternative of aria-rowindex.\n     * @see aria-colindextext.\n     */\n    'aria-rowindextext'?: string | null | undefined;\n    /**\n     * Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid.\n     * @see aria-rowindex @see aria-colspan.\n     */\n    'aria-rowspan'?: number | null | undefined;\n    /**\n     * Indicates the current \"selected\" state of various widgets.\n     * @see aria-checked @see aria-pressed.\n     */\n    'aria-selected'?: Booleanish | null | undefined;\n    /**\n     * Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM.\n     * @see aria-posinset.\n     */\n    'aria-setsize'?: number | null | undefined;\n    /** Indicates if items in a table or grid are sorted in ascending or descending order. */\n    'aria-sort'?:\n      | 'none'\n      | 'ascending'\n      | 'descending'\n      | 'other'\n      | null\n      | undefined;\n    /** Defines the maximum allowed value for a range widget. */\n    'aria-valuemax'?: number | null | undefined;\n    /** Defines the minimum allowed value for a range widget. */\n    'aria-valuemin'?: number | null | undefined;\n    /**\n     * Defines the current value for a range widget.\n     * @see aria-valuetext.\n     */\n    'aria-valuenow'?: number | null | undefined;\n    /** Defines the human readable text alternative of aria-valuenow for a range widget. */\n    'aria-valuetext'?: string | null | undefined;\n  }\n\n  // All the WAI-ARIA 1.1 role attribute values from https://www.w3.org/TR/wai-aria-1.1/#role_definitions\n  type AriaRole =\n    | 'alert'\n    | 'alertdialog'\n    | 'application'\n    | 'article'\n    | 'banner'\n    | 'button'\n    | 'cell'\n    | 'checkbox'\n    | 'columnheader'\n    | 'combobox'\n    | 'complementary'\n    | 'contentinfo'\n    | 'definition'\n    | 'dialog'\n    | 'directory'\n    | 'document'\n    | 'feed'\n    | 'figure'\n    | 'form'\n    | 'grid'\n    | 'gridcell'\n    | 'group'\n    | 'heading'\n    | 'img'\n    | 'link'\n    | 'list'\n    | 'listbox'\n    | 'listitem'\n    | 'log'\n    | 'main'\n    | 'marquee'\n    | 'math'\n    | 'menu'\n    | 'menubar'\n    | 'menuitem'\n    | 'menuitemcheckbox'\n    | 'menuitemradio'\n    | 'navigation'\n    | 'none'\n    | 'note'\n    | 'option'\n    | 'presentation'\n    | 'progressbar'\n    | 'radio'\n    | 'radiogroup'\n    | 'region'\n    | 'row'\n    | 'rowgroup'\n    | 'rowheader'\n    | 'scrollbar'\n    | 'search'\n    | 'searchbox'\n    | 'separator'\n    | 'slider'\n    | 'spinbutton'\n    | 'status'\n    | 'switch'\n    | 'tab'\n    | 'table'\n    | 'tablist'\n    | 'tabpanel'\n    | 'term'\n    | 'textbox'\n    | 'timer'\n    | 'toolbar'\n    | 'tooltip'\n    | 'tree'\n    | 'treegrid'\n    | 'treeitem'\n    | (string & {});\n\n  interface CssVariables {\n    [key: `--${string}`]: string;\n  }\n\n  interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {\n    // Inferno-specific Attributes\n    class?: string | null | undefined;\n    defaultChecked?: boolean | null | undefined;\n    defaultValue?: string | number | readonly string[] | null | undefined;\n\n    // Standard HTML Attributes\n    accessKey?: string | null | undefined;\n    autoCapitalize?:\n      | 'off'\n      | 'none'\n      | 'on'\n      | 'sentences'\n      | 'words'\n      | 'characters'\n      | null\n      | undefined\n      | (string & {});\n    autoFocus?: boolean | null | undefined;\n    className?: string | null | undefined;\n    contentEditable?:\n      | Booleanish\n      | 'inherit'\n      | 'plaintext-only'\n      | null\n      | undefined;\n    contextMenu?: string | null | undefined;\n    dir?: string | null | undefined;\n    draggable?: Booleanish | null | undefined;\n    enterKeyHint?:\n      | 'enter'\n      | 'done'\n      | 'go'\n      | 'next'\n      | 'previous'\n      | 'search'\n      | 'send'\n      | null\n      | undefined;\n    hidden?: boolean | null | undefined;\n    id?: string | null | undefined;\n    lang?: string | null | undefined;\n    nonce?: string | null | undefined;\n    slot?: string | null | undefined;\n    spellCheck?: Booleanish | null | undefined;\n    style?: PropertiesHyphen | string | null | undefined | CssVariables;\n    tabIndex?: number | null | undefined;\n    title?: string | null | undefined;\n    translate?: 'yes' | 'no' | null | undefined;\n\n    // Unknown\n    radioGroup?: string | null | undefined; // <command>, <menuitem>\n\n    // WAI-ARIA\n    role?: AriaRole | null | undefined;\n\n    // RDFa Attributes\n    about?: string | null | undefined;\n    content?: string | null | undefined;\n    datatype?: string | null | undefined;\n    inlist?: any;\n    prefix?: string | null | undefined;\n    property?: string | null | undefined;\n    rel?: string | null | undefined;\n    resource?: string | null | undefined;\n    rev?: string | null | undefined;\n    typeof?: string | null | undefined;\n    vocab?: string | null | undefined;\n\n    // Non-standard Attributes\n    autoCorrect?: string | null | undefined;\n    autoSave?: string | null | undefined;\n    color?: string | null | undefined;\n    itemProp?: string | null | undefined;\n    itemScope?: boolean | null | undefined;\n    itemType?: string | null | undefined;\n    itemID?: string | null | undefined;\n    itemRef?: string | null | undefined;\n    results?: number | null | undefined;\n    security?: string | null | undefined;\n    unselectable?: 'on' | 'off' | null | undefined;\n\n    // Living Standard\n    /**\n     * Hints at the type of data that might be entered by the user while editing the element or its contents\n     * @see {@link https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-inputmode-attribute}\n     */\n    inputMode?:\n      | 'none'\n      | 'text'\n      | 'tel'\n      | 'url'\n      | 'email'\n      | 'numeric'\n      | 'decimal'\n      | 'search'\n      | null\n      | undefined;\n    /**\n     * Specify that a standard HTML element should behave like a defined custom built-in element\n     * @see {@link https://html.spec.whatwg.org/multipage/custom-elements.html#attr-is}\n     */\n    is?: string | null | undefined;\n  }\n  interface AllHTMLAttributes<T> extends HTMLAttributes<T> {\n    // Standard HTML Attributes\n    accept?: string | null | undefined;\n    acceptCharset?: string | null | undefined;\n    action?: string | null | undefined;\n    allowFullScreen?: boolean | null | undefined;\n    allowTransparency?: boolean | null | undefined;\n    alt?: string | null | undefined;\n    as?: string | null | undefined;\n    async?: boolean | null | undefined;\n    autoComplete?: string | null | undefined;\n    autoPlay?: boolean | null | undefined;\n    capture?: boolean | 'user' | 'environment' | null | undefined;\n    cellPadding?: number | string | null | undefined;\n    cellSpacing?: number | string | null | undefined;\n    charSet?: string | null | undefined;\n    challenge?: string | null | undefined;\n    checked?: boolean | null | undefined;\n    cite?: string | null | undefined;\n    classID?: string | null | undefined;\n    cols?: number | null | undefined;\n    colSpan?: number | null | undefined;\n    controls?: boolean | null | undefined;\n    coords?: string | null | undefined;\n    crossOrigin?: CrossOrigin;\n    data?: string | null | undefined;\n    dateTime?: string | null | undefined;\n    default?: boolean | null | undefined;\n    defer?: boolean | null | undefined;\n    disabled?: boolean | null | undefined;\n    download?: any;\n    encType?: string | null | undefined;\n    form?: string | null | undefined;\n    formAction?: string | null | undefined;\n    formEncType?: string | null | undefined;\n    formMethod?: string | null | undefined;\n    formNoValidate?: boolean | null | undefined;\n    formTarget?: string | null | undefined;\n    frameBorder?: number | string | null | undefined;\n    headers?: string | null | undefined;\n    height?: number | string | null | undefined;\n    high?: number | null | undefined;\n    href?: string | null | undefined;\n    hrefLang?: string | null | undefined;\n    htmlFor?: string | null | undefined;\n    httpEquiv?: string | null | undefined;\n    integrity?: string | null | undefined;\n    keyParams?: string | null | undefined;\n    keyType?: string | null | undefined;\n    kind?: string | null | undefined;\n    label?: string | null | undefined;\n    list?: string | null | undefined;\n    loop?: boolean | null | undefined;\n    low?: number | null | undefined;\n    manifest?: string | null | undefined;\n    marginHeight?: number | null | undefined;\n    marginWidth?: number | null | undefined;\n    max?: number | string | null | undefined;\n    maxLength?: number | null | undefined;\n    media?: string | null | undefined;\n    mediaGroup?: string | null | undefined;\n    method?: string | null | undefined;\n    min?: number | string | null | undefined;\n    minLength?: number | null | undefined;\n    multiple?: boolean | null | undefined;\n    muted?: boolean | null | undefined;\n    name?: string | null | undefined;\n    noValidate?: boolean | null | undefined;\n    open?: boolean | null | undefined;\n    optimum?: number | null | undefined;\n    pattern?: string | null | undefined;\n    placeholder?: string | null | undefined;\n    playsInline?: boolean | null | undefined;\n    poster?: string | null | undefined;\n    preload?: string | null | undefined;\n    readOnly?: boolean | null | undefined;\n    required?: boolean | null | undefined;\n    reversed?: boolean | null | undefined;\n    rows?: number | null | undefined;\n    rowSpan?: number | null | undefined;\n    sandbox?: string | null | undefined;\n    scope?: string | null | undefined;\n    scoped?: boolean | null | undefined;\n    scrolling?: string | null | undefined;\n    seamless?: boolean | null | undefined;\n    selected?: boolean | null | undefined;\n    shape?: string | null | undefined;\n    size?: number | null | undefined;\n    sizes?: string | null | undefined;\n    span?: number | null | undefined;\n    src?: string | null | undefined;\n    srcDoc?: string | null | undefined;\n    srcLang?: string | null | undefined;\n    srcSet?: string | null | undefined;\n    start?: number | null | undefined;\n    step?: number | string | null | undefined;\n    summary?: string | null | undefined;\n    target?: string | null | undefined;\n    type?: string | null | undefined;\n    useMap?: string | null | undefined;\n    value?: string | readonly string[] | number | null | undefined;\n    width?: number | string | null | undefined;\n    wmode?: string | null | undefined;\n    wrap?: string | null | undefined;\n  }\n\n  type HTMLAttributeReferrerPolicy =\n    | ''\n    | 'no-referrer'\n    | 'no-referrer-when-downgrade'\n    | 'origin'\n    | 'origin-when-cross-origin'\n    | 'same-origin'\n    | 'strict-origin'\n    | 'strict-origin-when-cross-origin'\n    | 'unsafe-url';\n\n  type HTMLAttributeAnchorTarget =\n    | '_self'\n    | '_blank'\n    | '_parent'\n    | '_top'\n    | (string & {});\n\n  interface AnchorHTMLAttributes<T> extends HTMLAttributes<T> {\n    download?: any;\n    href?: string | null | undefined;\n    hrefLang?: string | null | undefined;\n    media?: string | null | undefined;\n    ping?: string | null | undefined;\n    target?: HTMLAttributeAnchorTarget | null | undefined;\n    type?: string | null | undefined;\n    referrerPolicy?: HTMLAttributeReferrerPolicy | null | undefined;\n  }\n\n  interface AudioHTMLAttributes<T> extends MediaHTMLAttributes<T> {}\n\n  interface AreaHTMLAttributes<T> extends HTMLAttributes<T> {\n    alt?: string | null | undefined;\n    coords?: string | null | undefined;\n    download?: any;\n    href?: string | null | undefined;\n    hrefLang?: string | null | undefined;\n    media?: string | null | undefined;\n    referrerPolicy?: HTMLAttributeReferrerPolicy | null | undefined;\n    shape?: string | null | undefined;\n    target?: string | null | undefined;\n  }\n\n  interface BaseHTMLAttributes<T> extends HTMLAttributes<T> {\n    href?: string | null | undefined;\n    target?: string | null | undefined;\n  }\n\n  interface BlockquoteHTMLAttributes<T> extends HTMLAttributes<T> {\n    cite?: string | null | undefined;\n  }\n\n  interface ButtonHTMLAttributes<T> extends HTMLAttributes<T> {\n    disabled?: boolean | null | undefined;\n    form?: string | null | undefined;\n    formAction?: string | null | undefined;\n    formEncType?: string | null | undefined;\n    formMethod?: string | null | undefined;\n    formNoValidate?: boolean | null | undefined;\n    formTarget?: string | null | undefined;\n    name?: string | null | undefined;\n    type?: 'submit' | 'reset' | 'button' | null | undefined;\n    value?: string | readonly string[] | number | null | undefined;\n  }\n\n  interface CanvasHTMLAttributes<T> extends HTMLAttributes<T> {\n    height?: number | string | null | undefined;\n    width?: number | string | null | undefined;\n  }\n\n  interface ColHTMLAttributes<T> extends HTMLAttributes<T> {\n    span?: number | null | undefined;\n    width?: number | string | null | undefined;\n  }\n\n  interface ColgroupHTMLAttributes<T> extends HTMLAttributes<T> {\n    span?: number | null | undefined;\n  }\n\n  interface DataHTMLAttributes<T> extends HTMLAttributes<T> {\n    value?: string | readonly string[] | number | null | undefined;\n  }\n\n  interface DetailsHTMLAttributes<T> extends HTMLAttributes<T> {\n    open?: boolean | null | undefined;\n    onToggle?: InfernoEventHandler<T> | null | undefined;\n    name?: string | null | undefined;\n  }\n\n  interface DelHTMLAttributes<T> extends HTMLAttributes<T> {\n    cite?: string | null | undefined;\n    dateTime?: string | null | undefined;\n  }\n\n  interface DialogHTMLAttributes<T> extends HTMLAttributes<T> {\n    onCancel?: InfernoEventHandler<T> | null | undefined;\n    onClose?: InfernoEventHandler<T> | null | undefined;\n    open?: boolean | null | undefined;\n  }\n\n  interface EmbedHTMLAttributes<T> extends HTMLAttributes<T> {\n    height?: number | string | null | undefined;\n    src?: string | null | undefined;\n    type?: string | null | undefined;\n    width?: number | string | null | undefined;\n  }\n\n  interface FieldsetHTMLAttributes<T> extends HTMLAttributes<T> {\n    disabled?: boolean | null | undefined;\n    form?: string | null | undefined;\n    name?: string | null | undefined;\n  }\n\n  interface FormHTMLAttributes<T> extends HTMLAttributes<T> {\n    acceptCharset?: string | null | undefined;\n    action?: string | null | undefined;\n    autoComplete?: string | null | undefined;\n    encType?: string | null | undefined;\n    method?: string | null | undefined;\n    name?: string | null | undefined;\n    noValidate?: boolean | null | undefined;\n    target?: string | null | undefined;\n  }\n\n  interface HtmlHTMLAttributes<T> extends HTMLAttributes<T> {\n    manifest?: string | null | undefined;\n  }\n\n  interface IframeHTMLAttributes<T> extends HTMLAttributes<T> {\n    allow?: string | null | undefined;\n    allowFullScreen?: boolean | null | undefined;\n    allowTransparency?: boolean | null | undefined;\n    /** @deprecated */\n    frameBorder?: number | string | null | undefined;\n    height?: number | string | null | undefined;\n    loading?: 'eager' | 'lazy' | null | undefined;\n    /** @deprecated */\n    marginHeight?: number | null | undefined;\n    /** @deprecated */\n    marginWidth?: number | null | undefined;\n    name?: string | null | undefined;\n    referrerPolicy?: HTMLAttributeReferrerPolicy | null | undefined;\n    sandbox?: string | null | undefined;\n    /** @deprecated */\n    scrolling?: string | null | undefined;\n    seamless?: boolean | null | undefined;\n    src?: string | null | undefined;\n    srcDoc?: string | null | undefined;\n    width?: number | string | null | undefined;\n  }\n\n  interface ImgHTMLAttributes<T> extends HTMLAttributes<T> {\n    alt?: string | null | undefined;\n    crossOrigin?: CrossOrigin;\n    decoding?: 'async' | 'auto' | 'sync' | null | undefined;\n    fetchPriority?: 'high' | 'low' | 'auto';\n    height?: number | string | null | undefined;\n    loading?: 'eager' | 'lazy' | null | undefined;\n    referrerPolicy?: HTMLAttributeReferrerPolicy | null | undefined;\n    sizes?: string | null | undefined;\n    src?: string | null | undefined;\n    srcSet?: string | null | undefined;\n    useMap?: string | null | undefined;\n    width?: number | string | null | undefined;\n  }\n\n  interface InsHTMLAttributes<T> extends HTMLAttributes<T> {\n    cite?: string | null | undefined;\n    dateTime?: string | null | undefined;\n  }\n\n  type HTMLInputTypeAttribute =\n    | 'button'\n    | 'checkbox'\n    | 'color'\n    | 'date'\n    | 'datetime-local'\n    | 'email'\n    | 'file'\n    | 'hidden'\n    | 'image'\n    | 'month'\n    | 'number'\n    | 'password'\n    | 'radio'\n    | 'range'\n    | 'reset'\n    | 'search'\n    | 'submit'\n    | 'tel'\n    | 'text'\n    | 'time'\n    | 'url'\n    | 'week'\n    | (string & {});\n\n  type AutoFillAddressKind = 'billing' | 'shipping';\n  type AutoFillBase = '' | 'off' | 'on';\n  type AutoFillContactField =\n    | 'email'\n    | 'tel'\n    | 'tel-area-code'\n    | 'tel-country-code'\n    | 'tel-extension'\n    | 'tel-local'\n    | 'tel-local-prefix'\n    | 'tel-local-suffix'\n    | 'tel-national';\n  type AutoFillContactKind = 'home' | 'mobile' | 'work';\n  type AutoFillCredentialField = 'webauthn';\n  type AutoFillNormalField =\n    | 'additional-name'\n    | 'address-level1'\n    | 'address-level2'\n    | 'address-level3'\n    | 'address-level4'\n    | 'address-line1'\n    | 'address-line2'\n    | 'address-line3'\n    | 'bday-day'\n    | 'bday-month'\n    | 'bday-year'\n    | 'cc-csc'\n    | 'cc-exp'\n    | 'cc-exp-month'\n    | 'cc-exp-year'\n    | 'cc-family-name'\n    | 'cc-given-name'\n    | 'cc-name'\n    | 'cc-number'\n    | 'cc-type'\n    | 'country'\n    | 'country-name'\n    | 'current-password'\n    | 'family-name'\n    | 'given-name'\n    | 'honorific-prefix'\n    | 'honorific-suffix'\n    | 'name'\n    | 'new-password'\n    | 'one-time-code'\n    | 'organization'\n    | 'postal-code'\n    | 'street-address'\n    | 'transaction-amount'\n    | 'transaction-currency'\n    | 'username';\n  type OptionalPrefixToken<T extends string> = `${T} ` | '';\n  type OptionalPostfixToken<T extends string> = ` ${T}` | '';\n  type AutoFillField =\n    | AutoFillNormalField\n    | `${OptionalPrefixToken<AutoFillContactKind>}${AutoFillContactField}`;\n  type AutoFillSection = `section-${string}`;\n  type AutoFill =\n    | AutoFillBase\n    | `${OptionalPrefixToken<AutoFillSection>}${OptionalPrefixToken<AutoFillAddressKind>}${AutoFillField}${OptionalPostfixToken<AutoFillCredentialField>}`;\n  type HTMLInputAutoCompleteAttribute = AutoFill | (string & {});\n\n  interface InputHTMLAttributes<T> extends HTMLAttributes<T> {\n    accept?: string | null | undefined;\n    alt?: string | null | undefined;\n    autoComplete?: HTMLInputAutoCompleteAttribute | null | undefined;\n    capture?: boolean | 'user' | 'environment' | null | undefined; // https://www.w3.org/TR/html-media-capture/#the-capture-attribute\n    checked?: boolean | null | undefined;\n    disabled?: boolean | null | undefined;\n    form?: string | null | undefined;\n    formAction?: string | null | undefined;\n    formEncType?: string | null | undefined;\n    formMethod?: string | null | undefined;\n    formNoValidate?: boolean | null | undefined;\n    formTarget?: string | null | undefined;\n    height?: number | string | null | undefined;\n    indeterminate?: boolean | null | undefined;\n    list?: string | null | undefined;\n    max?: number | string | null | undefined;\n    maxLength?: number | null | undefined;\n    min?: number | string | null | undefined;\n    minLength?: number | null | undefined;\n    multiple?: boolean | null | undefined;\n    name?: string | null | undefined;\n    pattern?: string | null | undefined;\n    placeholder?: string | null | undefined;\n    readOnly?: boolean | null | undefined;\n    required?: boolean | null | undefined;\n    size?: number | null | undefined;\n    src?: string | null | undefined;\n    step?: number | string | null | undefined;\n    type?: HTMLInputTypeAttribute | null | undefined;\n    value?: string | readonly string[] | number | null | undefined;\n    width?: number | string | null | undefined;\n  }\n\n  interface KeygenHTMLAttributes<T> extends HTMLAttributes<T> {\n    challenge?: string | null | undefined;\n    disabled?: boolean | null | undefined;\n    form?: string | null | undefined;\n    keyType?: string | null | undefined;\n    keyParams?: string | null | undefined;\n    name?: string | null | undefined;\n  }\n\n  interface LabelHTMLAttributes<T> extends HTMLAttributes<T> {\n    form?: string | null | undefined;\n    htmlFor?: string | null | undefined;\n    for?: string | null | undefined;\n  }\n\n  interface LiHTMLAttributes<T> extends HTMLAttributes<T> {\n    value?: string | readonly string[] | number | null | undefined;\n  }\n\n  interface LinkHTMLAttributes<T> extends HTMLAttributes<T> {\n    as?: string | null | undefined;\n    crossOrigin?: CrossOrigin;\n    fetchPriority?: 'high' | 'low' | 'auto';\n    href?: string | null | undefined;\n    hrefLang?: string | null | undefined;\n    integrity?: string | null | undefined;\n    media?: string | null | undefined;\n    imageSrcSet?: string | null | undefined;\n    imageSizes?: string | null | undefined;\n    referrerPolicy?: HTMLAttributeReferrerPolicy | null | undefined;\n    sizes?: string | null | undefined;\n    type?: string | null | undefined;\n    charSet?: string | null | undefined;\n  }\n\n  interface MapHTMLAttributes<T> extends HTMLAttributes<T> {\n    name?: string | null | undefined;\n  }\n\n  interface MenuHTMLAttributes<T> extends HTMLAttributes<T> {\n    type?: string | null | undefined;\n  }\n\n  interface MediaHTMLAttributes<T> extends HTMLAttributes<T> {\n    autoPlay?: boolean | null | undefined;\n    controls?: boolean | null | undefined;\n    controlsList?: string | null | undefined;\n    crossOrigin?: CrossOrigin;\n    loop?: boolean | null | undefined;\n    mediaGroup?: string | null | undefined;\n    muted?: boolean | null | undefined;\n    playsInline?: boolean | null | undefined;\n    preload?: string | null | undefined;\n    src?: string | null | undefined;\n  }\n\n  interface MetaHTMLAttributes<T> extends HTMLAttributes<T> {\n    charSet?: string | null | undefined;\n    content?: string | null | undefined;\n    httpEquiv?: string | null | undefined;\n    media?: string | null | undefined;\n    name?: string | null | undefined;\n  }\n\n  interface MeterHTMLAttributes<T> extends HTMLAttributes<T> {\n    form?: string | null | undefined;\n    high?: number | null | undefined;\n    low?: number | null | undefined;\n    max?: number | string | null | undefined;\n    min?: number | string | null | undefined;\n    optimum?: number | null | undefined;\n    value?: string | readonly string[] | number | null | undefined;\n  }\n\n  interface QuoteHTMLAttributes<T> extends HTMLAttributes<T> {\n    cite?: string | null | undefined;\n  }\n\n  interface ObjectHTMLAttributes<T> extends HTMLAttributes<T> {\n    classID?: string | null | undefined;\n    data?: string | null | undefined;\n    form?: string | null | undefined;\n    height?: number | string | null | undefined;\n    name?: string | null | undefined;\n    type?: string | null | undefined;\n    useMap?: string | null | undefined;\n    width?: number | string | null | undefined;\n    wmode?: string | null | undefined;\n  }\n\n  interface OlHTMLAttributes<T> extends HTMLAttributes<T> {\n    reversed?: boolean | null | undefined;\n    start?: number | null | undefined;\n    type?: '1' | 'a' | 'A' | 'i' | 'I' | null | undefined;\n  }\n\n  interface OptgroupHTMLAttributes<T> extends HTMLAttributes<T> {\n    disabled?: boolean | null | undefined;\n    label?: string | null | undefined;\n  }\n\n  interface OptionHTMLAttributes<T> extends HTMLAttributes<T> {\n    disabled?: boolean | null | undefined;\n    label?: string | null | undefined;\n    selected?: boolean | null | undefined;\n    value?: string | readonly string[] | number | null | undefined;\n  }\n\n  interface OutputHTMLAttributes<T> extends HTMLAttributes<T> {\n    form?: string | null | undefined;\n    htmlFor?: string | null | undefined;\n    name?: string | null | undefined;\n  }\n\n  interface ParamHTMLAttributes<T> extends HTMLAttributes<T> {\n    name?: string | null | undefined;\n    value?: string | readonly string[] | number | null | undefined;\n  }\n\n  interface ProgressHTMLAttributes<T> extends HTMLAttributes<T> {\n    max?: number | string | null | undefined;\n    value?: string | readonly string[] | number | null | undefined;\n  }\n\n  interface SlotHTMLAttributes<T> extends HTMLAttributes<T> {\n    name?: string | null | undefined;\n  }\n\n  interface ScriptHTMLAttributes<T> extends HTMLAttributes<T> {\n    async?: boolean | null | undefined;\n    /** @deprecated */\n    charSet?: string | null | undefined;\n    crossOrigin?: CrossOrigin;\n    defer?: boolean | null | undefined;\n    integrity?: string | null | undefined;\n    noModule?: boolean | null | undefined;\n    referrerPolicy?: HTMLAttributeReferrerPolicy | null | undefined;\n    src?: string | null | undefined;\n    type?: string | null | undefined;\n  }\n\n  interface SelectHTMLAttributes<T> extends HTMLAttributes<T> {\n    autoComplete?: string | null | undefined;\n    disabled?: boolean | null | undefined;\n    form?: string | null | undefined;\n    multiple?: boolean | null | undefined;\n    name?: string | null | undefined;\n    required?: boolean | null | undefined;\n    size?: number | null | undefined;\n    value?: string | readonly string[] | number | null | undefined;\n    selectedIndex?: number | null | undefined;\n  }\n\n  interface SourceHTMLAttributes<T> extends HTMLAttributes<T> {\n    height?: number | string | null | undefined;\n    media?: string | null | undefined;\n    sizes?: string | null | undefined;\n    src?: string | null | undefined;\n    srcSet?: string | null | undefined;\n    type?: string | null | undefined;\n    width?: number | string | null | undefined;\n  }\n\n  interface StyleHTMLAttributes<T> extends HTMLAttributes<T> {\n    media?: string | null | undefined;\n    scoped?: boolean | null | undefined;\n    type?: string | null | undefined;\n  }\n\n  interface TableHTMLAttributes<T> extends HTMLAttributes<T> {\n    align?: 'left' | 'center' | 'right' | null | undefined;\n    bgcolor?: string | null | undefined;\n    border?: number | null | undefined;\n    cellPadding?: number | string | null | undefined;\n    cellSpacing?: number | string | null | undefined;\n    frame?: boolean | null | undefined;\n    rules?: 'none' | 'groups' | 'rows' | 'columns' | 'all' | null | undefined;\n    summary?: string | null | undefined;\n    width?: number | string | null | undefined;\n  }\n\n  interface TextareaHTMLAttributes<T> extends HTMLAttributes<T> {\n    autoComplete?: string | null | undefined;\n    autoFocus?: boolean | null | undefined;\n    cols?: number | null | undefined;\n    dirName?: string | null | undefined;\n    disabled?: boolean | null | undefined;\n    form?: string | null | undefined;\n    maxLength?: number | null | undefined;\n    minLength?: number | null | undefined;\n    name?: string | null | undefined;\n    placeholder?: string | null | undefined;\n    readOnly?: boolean | null | undefined;\n    required?: boolean | null | undefined;\n    rows?: number | null | undefined;\n    value?: string | readonly string[] | number | null | undefined;\n    wrap?: string | null | undefined;\n  }\n\n  interface TdHTMLAttributes<T> extends HTMLAttributes<T> {\n    align?: 'left' | 'center' | 'right' | 'justify' | 'char' | null | undefined;\n    colSpan?: number | null | undefined;\n    headers?: string | null | undefined;\n    rowSpan?: number | null | undefined;\n    scope?: string | null | undefined;\n    abbr?: string | null | undefined;\n    height?: number | string | null | undefined;\n    width?: number | string | null | undefined;\n    valign?: 'top' | 'middle' | 'bottom' | 'baseline' | null | undefined;\n  }\n\n  interface ThHTMLAttributes<T> extends HTMLAttributes<T> {\n    align?: 'left' | 'center' | 'right' | 'justify' | 'char' | null | undefined;\n    colSpan?: number | null | undefined;\n    headers?: string | null | undefined;\n    rowSpan?: number | null | undefined;\n    scope?: string | null | undefined;\n    abbr?: string | null | undefined;\n  }\n\n  interface TimeHTMLAttributes<T> extends HTMLAttributes<T> {\n    dateTime?: string | null | undefined;\n  }\n\n  interface TrackHTMLAttributes<T> extends HTMLAttributes<T> {\n    default?: boolean | null | undefined;\n    kind?: string | null | undefined;\n    label?: string | null | undefined;\n    src?: string | null | undefined;\n    srcLang?: string | null | undefined;\n  }\n\n  interface VideoHTMLAttributes<T> extends MediaHTMLAttributes<T> {\n    type?: string | null | undefined;\n    height?: number | string | null | undefined;\n    playsInline?: boolean | null | undefined;\n    poster?: string | null | undefined;\n    width?: number | string | null | undefined;\n    disablePictureInPicture?: boolean | null | undefined;\n    disableRemotePlayback?: boolean | null | undefined;\n  }\n\n  // this list is \"complete\" in that it contains every SVG attribute\n  //\n  // The three broad type categories are (in order of restrictiveness):\n  //   - \"number | string\"\n  //   - \"string\"\n  //   - union of string literals\n  interface SVGAttributes<T> extends AriaAttributes, DOMAttributes<T> {\n    class?: string | null | undefined;\n\n    // Attributes which also defined in HTMLAttributes\n    // See comment in SVGDOMPropertyConfig.js\n    className?: string | null | undefined;\n    color?: string | null | undefined;\n    height?: number | string | null | undefined;\n    id?: string | null | undefined;\n    lang?: string | null | undefined;\n    max?: number | string | null | undefined;\n    media?: string | null | undefined;\n    method?: string | null | undefined;\n    min?: number | string | null | undefined;\n    name?: string | null | undefined;\n    style?: any;\n    target?: string | null | undefined;\n    type?: string | null | undefined;\n    width?: number | string | null | undefined;\n\n    // Other HTML properties supported by SVG elements in browsers\n    role?: AriaRole | null | undefined;\n    tabIndex?: number | null | undefined;\n    crossOrigin?: 'anonymous' | 'use-credentials' | '' | null | undefined;\n\n    // SVG Specific attributes\n    accentHeight?: number | string | null | undefined;\n    'accent-height'?: number | string | null | undefined;\n    accumulate?: 'none' | 'sum' | null | undefined;\n    additive?: 'replace' | 'sum' | null | undefined;\n    alignmentBaseline?:\n      | 'auto'\n      | 'baseline'\n      | 'before-edge'\n      | 'text-before-edge'\n      | 'middle'\n      | 'central'\n      | 'after-edge'\n      | 'text-after-edge'\n      | 'ideographic'\n      | 'alphabetic'\n      | 'hanging'\n      | 'mathematical'\n      | 'inherit'\n      | null\n      | undefined;\n    'alignment-baseline'?:\n      | 'auto'\n      | 'baseline'\n      | 'before-edge'\n      | 'text-before-edge'\n      | 'middle'\n      | 'central'\n      | 'after-edge'\n      | 'text-after-edge'\n      | 'ideographic'\n      | 'alphabetic'\n      | 'hanging'\n      | 'mathematical'\n      | 'inherit'\n      | null\n      | undefined;\n    allowReorder?: 'no' | 'yes' | null | undefined;\n    alphabetic?: number | string | null | undefined;\n    amplitude?: number | string | null | undefined;\n    arabicForm?:\n      | 'initial'\n      | 'medial'\n      | 'terminal'\n      | 'isolated'\n      | null\n      | undefined;\n    'arabic-form'?:\n      | 'initial'\n      | 'medial'\n      | 'terminal'\n      | 'isolated'\n      | null\n      | undefined;\n    ascent?: number | string | null | undefined;\n    attributeName?: string | null | undefined;\n    attributeType?: string | null | undefined;\n    autoReverse?: Booleanish | null | undefined;\n    azimuth?: number | string | null | undefined;\n    baseFrequency?: number | string | null | undefined;\n    baselineShift?: number | string | null | undefined;\n    'baseline-shift'?: number | string | null | undefined;\n    baseProfile?: number | string | null | undefined;\n    bbox?: number | string | null | undefined;\n    begin?: number | string | null | undefined;\n    bias?: number | string | null | undefined;\n    by?: number | string | null | undefined;\n    calcMode?: number | string | null | undefined;\n    capHeight?: number | string | null | undefined;\n    'cap-height'?: number | string | null | undefined;\n    clip?: number | string | null | undefined;\n    clipPath?: string | null | undefined;\n    'clip-path'?: string | null | undefined;\n    clipPathUnits?: number | string | null | undefined;\n    clipRule?: number | string | null | undefined;\n    'clip-rule'?: number | string | null | undefined;\n    colorInterpolation?: number | string | null | undefined;\n    'color-interpolation'?: number | string | null | undefined;\n    colorInterpolationFilters?:\n      | 'auto'\n      | 'sRGB'\n      | 'linearRGB'\n      | 'inherit'\n      | null\n      | undefined;\n    'color-interpolation-filters'?:\n      | 'auto'\n      | 'sRGB'\n      | 'linearRGB'\n      | 'inherit'\n      | null\n      | undefined;\n    colorProfile?: number | string | null | undefined;\n    'color-profile'?: number | string | null | undefined;\n    colorRendering?: number | string | null | undefined;\n    'color-rendering'?: number | string | null | undefined;\n    contentScriptType?: number | string | null | undefined;\n    contentStyleType?: number | string | null | undefined;\n    cursor?: number | string | null | undefined;\n    cx?: number | string | null | undefined;\n    cy?: number | string | null | undefined;\n    d?: string | null | undefined;\n    decelerate?: number | string | null | undefined;\n    descent?: number | string | null | undefined;\n    diffuseConstant?: number | string | null | undefined;\n    direction?: number | string | null | undefined;\n    display?: number | string | null | undefined;\n    divisor?: number | string | null | undefined;\n    dominantBaseline?: number | string | null | undefined;\n    'dominant-baseline'?: number | string | null | undefined;\n    dur?: number | string | null | undefined;\n    dx?: number | string | null | undefined;\n    dy?: number | string | null | undefined;\n    edgeMode?: number | string | null | undefined;\n    elevation?: number | string | null | undefined;\n    enableBackground?: number | string | null | undefined;\n    'enable-background'?: number | string | null | undefined;\n    end?: number | string | null | undefined;\n    exponent?: number | string | null | undefined;\n    externalResourcesRequired?: Booleanish | null | undefined;\n    fill?: string | null | undefined;\n    fillOpacity?: number | string | null | undefined;\n    'fill-opacity'?: number | string | null | undefined;\n    fillRule?: 'nonzero' | 'evenodd' | 'inherit' | null | undefined;\n    'fill-rule'?: 'nonzero' | 'evenodd' | 'inherit' | null | undefined;\n    filter?: string | null | undefined;\n    filterRes?: number | string | null | undefined;\n    filterUnits?: number | string | null | undefined;\n    floodColor?: number | string | null | undefined;\n    'flood-color'?: number | string | null | undefined;\n    floodOpacity?: number | string | null | undefined;\n    'flood-opacity'?: number | string | null | undefined;\n    focusable?: Booleanish | 'auto' | null | undefined;\n    fontFamily?: string | null | undefined;\n    'font-family'?: string | null | undefined;\n    fontSize?: number | string | null | undefined;\n    'font-size'?: number | string | null | undefined;\n    fontSizeAdjust?: number | string | null | undefined;\n    'font-size-adjust'?: number | string | null | undefined;\n    fontStretch?: number | string | null | undefined;\n    'font-stretch'?: number | string | null | undefined;\n    fontStyle?: number | string | null | undefined;\n    'font-style'?: number | string | null | undefined;\n    fontVariant?: number | string | null | undefined;\n    'font-variant'?: number | string | null | undefined;\n    fontWeight?: number | string | null | undefined;\n    'font-weight'?: number | string | null | undefined;\n    format?: number | string | null | undefined;\n    fr?: number | string | null | undefined;\n    from?: number | string | null | undefined;\n    fx?: number | string | null | undefined;\n    fy?: number | string | null | undefined;\n    g1?: number | string | null | undefined;\n    g2?: number | string | null | undefined;\n    glyphName?: number | string | null | undefined;\n    'glyph-name'?: number | string | null | undefined;\n    glyphOrientationHorizontal?: number | string | null | undefined;\n    'glyph-orientation-horizontal'?: number | string | null | undefined;\n    glyphOrientationVertical?: number | string | null | undefined;\n    'glyph-orientation-vertical'?: number | string | null | undefined;\n    glyphRef?: number | string | null | undefined;\n    gradientTransform?: string | null | undefined;\n    gradientUnits?: string | null | undefined;\n    hanging?: number | string | null | undefined;\n    horizAdvX?: number | string | null | undefined;\n    'horiz-advX'?: number | string | null | undefined;\n    horizOriginX?: number | string | null | undefined;\n    'horiz-origin-x'?: number | string | null | undefined;\n    href?: string | null | undefined;\n    ideographic?: number | string | null | undefined;\n    imageRendering?: number | string | null | undefined;\n    'image-rendering'?: number | string | null | undefined;\n    in2?: number | string | null | undefined;\n    in?: string | null | undefined;\n    intercept?: number | string | null | undefined;\n    k1?: number | string | null | undefined;\n    k2?: number | string | null | undefined;\n    k3?: number | string | null | undefined;\n    k4?: number | string | null | undefined;\n    k?: number | string | null | undefined;\n    kernelMatrix?: number | string | null | undefined;\n    kernelUnitLength?: number | string | null | undefined;\n    kerning?: number | string | null | undefined;\n    keyPoints?: number | string | null | undefined;\n    keySplines?: number | string | null | undefined;\n    keyTimes?: number | string | null | undefined;\n    lengthAdjust?: number | string | null | undefined;\n    letterSpacing?: number | string | null | undefined;\n    'letter-spacing'?: number | string | null | undefined;\n    lightingColor?: number | string | null | undefined;\n    'lighting-color'?: number | string | null | undefined;\n    limitingConeAngle?: number | string | null | undefined;\n    local?: number | string | null | undefined;\n    markerEnd?: string | null | undefined;\n    'marker-end'?: string | null | undefined;\n    markerHeight?: number | string | null | undefined;\n    'marker-height'?: number | string | null | undefined;\n    markerMid?: string | null | undefined;\n    'marker-mid'?: string | null | undefined;\n    markerStart?: string | null | undefined;\n    'marker-start'?: string | null | undefined;\n    markerUnits?: number | string | null | undefined;\n    markerWidth?: number | string | null | undefined;\n    mask?: string | null | undefined;\n    maskContentUnits?: number | string | null | undefined;\n    maskUnits?: number | string | null | undefined;\n    mathematical?: number | string | null | undefined;\n    mode?: number | string | null | undefined;\n    numOctaves?: number | string | null | undefined;\n    offset?: number | string | null | undefined;\n    opacity?: number | string | null | undefined;\n    operator?: number | string | null | undefined;\n    order?: number | string | null | undefined;\n    orient?: number | string | null | undefined;\n    orientation?: number | string | null | undefined;\n    origin?: number | string | null | undefined;\n    overflow?: number | string | null | undefined;\n    overlinePosition?: number | string | null | undefined;\n    'overline-position'?: number | string | null | undefined;\n    overlineThickness?: number | string | null | undefined;\n    'overline-thickness'?: number | string | null | undefined;\n    paintOrder?: number | string | null | undefined;\n    'paint-order'?: number | string | null | undefined;\n    panose1?: number | string | null | undefined;\n    'panose-1'?: number | string | null | undefined;\n    path?: string | null | undefined;\n    pathLength?: number | string | null | undefined;\n    patternContentUnits?: string | null | undefined;\n    patternTransform?: number | string | null | undefined;\n    patternUnits?: string | null | undefined;\n    pointerEvents?: number | string | null | undefined;\n    'pointer-events'?: number | string | null | undefined;\n    points?: string | null | undefined;\n    pointsAtX?: number | string | null | undefined;\n    pointsAtY?: number | string | null | undefined;\n    pointsAtZ?: number | string | null | undefined;\n    preserveAlpha?: Booleanish | null | undefined;\n    preserveAspectRatio?: string | null | undefined;\n    primitiveUnits?: number | string | null | undefined;\n    r?: number | string | null | undefined;\n    radius?: number | string | null | undefined;\n    refX?: number | string | null | undefined;\n    refY?: number | string | null | undefined;\n    renderingIntent?: number | string | null | undefined;\n    'rendering-intent'?: number | string | null | undefined;\n    repeatCount?: number | string | null | undefined;\n    repeatDur?: number | string | null | undefined;\n    requiredExtensions?: number | string | null | undefined;\n    requiredFeatures?: number | string | null | undefined;\n    restart?: number | string | null | undefined;\n    result?: string | null | undefined;\n    rotate?: number | string | null | undefined;\n    rx?: number | string | null | undefined;\n    ry?: number | string | null | undefined;\n    scale?: number | string | null | undefined;\n    seed?: number | string | null | undefined;\n    shapeRendering?: number | string | null | undefined;\n    'shape-rendering'?: number | string | null | undefined;\n    slope?: number | string | null | undefined;\n    spacing?: number | string | null | undefined;\n    specularConstant?: number | string | null | undefined;\n    specularExponent?: number | string | null | undefined;\n    speed?: number | string | null | undefined;\n    spreadMethod?: string | null | undefined;\n    startOffset?: number | string | null | undefined;\n    stdDeviation?: number | string | null | undefined;\n    stemh?: number | string | null | undefined;\n    stemv?: number | string | null | undefined;\n    stitchTiles?: number | string | null | undefined;\n    stopColor?: string | null | undefined;\n    'stop-color'?: string | null | undefined;\n    stopOpacity?: number | string | null | undefined;\n    'stop-opacity'?: number | string | null | undefined;\n    strikethroughPosition?: number | string | null | undefined;\n    'strikethrough-position'?: number | string | null | undefined;\n    strikethroughThickness?: number | string | null | undefined;\n    'strikethrough-thickness'?: number | string | null | undefined;\n    string?: number | string | null | undefined;\n    stroke?: string | null | undefined;\n    strokeDasharray?: string | number | null | undefined;\n    'stroke-dasharray'?: string | number | null | undefined;\n    strokeDashoffset?: string | number | null | undefined;\n    'stroke-dashoffset'?: string | number | null | undefined;\n    strokeLinecap?: 'butt' | 'round' | 'square' | 'inherit' | null | undefined;\n    'stroke-linecap'?:\n      | 'butt'\n      | 'round'\n      | 'square'\n      | 'inherit'\n      | null\n      | undefined;\n    strokeLinejoin?: 'miter' | 'round' | 'bevel' | 'inherit' | null | undefined;\n    'stroke-linejoin'?:\n      | 'miter'\n      | 'round'\n      | 'bevel'\n      | 'inherit'\n      | null\n      | undefined;\n    strokeMiterlimit?: number | string | null | undefined;\n    'stroke-miterlimit'?: number | string | null | undefined;\n    strokeOpacity?: number | string | null | undefined;\n    'stroke-opacity'?: number | string | null | undefined;\n    strokeWidth?: number | string | null | undefined;\n    'stroke-width'?: number | string | null | undefined;\n    surfaceScale?: number | string | null | undefined;\n    systemLanguage?: number | string | null | undefined;\n    tableValues?: number | string | null | undefined;\n    targetX?: number | string | null | undefined;\n    targetY?: number | string | null | undefined;\n    textAnchor?: string | null | undefined;\n    textDecoration?: number | string | null | undefined;\n    'text-decoration'?: number | string | null | undefined;\n    textLength?: number | string | null | undefined;\n    textRendering?: number | string | null | undefined;\n    'text-rendering'?: number | string | null | undefined;\n    to?: number | string | null | undefined;\n    transform?: string | null | undefined;\n    u1?: number | string | null | undefined;\n    u2?: number | string | null | undefined;\n    underlinePosition?: number | string | null | undefined;\n    'underline-position'?: number | string | null | undefined;\n    underlineThickness?: number | string | null | undefined;\n    'underline-thickness'?: number | string | null | undefined;\n    unicode?: number | string | null | undefined;\n    unicodeBidi?: number | string | null | undefined;\n    'unicode-bidi'?: number | string | null | undefined;\n    unicodeRange?: number | string | null | undefined;\n    'unicode-range'?: number | string | null | undefined;\n    unitsPerEm?: number | string | null | undefined;\n    'units-per-em'?: number | string | null | undefined;\n    vAlphabetic?: number | string | null | undefined;\n    'v-alphabetic'?: number | string | null | undefined;\n    values?: string | null | undefined;\n    vectorEffect?: number | string | null | undefined;\n    'vector-effect'?: number | string | null | undefined;\n    version?: string | null | undefined;\n    vertAdvY?: number | string | null | undefined;\n    'vert-adv-y'?: number | string | null | undefined;\n    vertOriginX?: number | string | null | undefined;\n    'vert-origin-x'?: number | string | null | undefined;\n    vertOriginY?: number | string | null | undefined;\n    'vert-origin-y'?: number | string | null | undefined;\n    vHanging?: number | string | null | undefined;\n    'v-hanging'?: number | string | null | undefined;\n    vIdeographic?: number | string | null | undefined;\n    'v-ideographic'?: number | string | null | undefined;\n    viewBox?: string | null | undefined;\n    viewTarget?: number | string | null | undefined;\n    visibility?: number | string | null | undefined;\n    vMathematical?: number | string | null | undefined;\n    'v-mathematical'?: number | string | null | undefined;\n    widths?: number | string | null | undefined;\n    wordSpacing?: number | string | null | undefined;\n    'word-spacing'?: number | string | null | undefined;\n    writingMode?: number | string | null | undefined;\n    'writing-mode'?: number | string | null | undefined;\n    x1?: number | string | null | undefined;\n    x2?: number | string | null | undefined;\n    x?: number | string | null | undefined;\n    xChannelSelector?: string | null | undefined;\n    xHeight?: number | string | null | undefined;\n    'x-height'?: number | string | null | undefined;\n    xlinkActuate?: string | null | undefined;\n    'xlink:actuate'?: string | null | undefined;\n    xlinkArcrole?: string | null | undefined;\n    'xlink:arcrole'?: string | null | undefined;\n    xlinkHref?: string | null | undefined;\n    'xlink:href'?: string | null | undefined;\n    xlinkRole?: string | null | undefined;\n    'xlink:role'?: string | null | undefined;\n    xlinkShow?: string | null | undefined;\n    'xlink:show'?: string | null | undefined;\n    xlinkTitle?: string | null | undefined;\n    'xlink:title'?: string | null | undefined;\n    xlinkType?: string | null | undefined;\n    'xlink:type'?: string | null | undefined;\n    xmlBase?: string | null | undefined;\n    'xml:base'?: string | null | undefined;\n    xmlLang?: string | null | undefined;\n    'xml:lang'?: string | null | undefined;\n    xmlns?: string | null | undefined;\n    xmlnsXlink?: string | null | undefined;\n    'xmlns:xlink'?: string | null | undefined;\n    xmlSpace?: string | null | undefined;\n    'xml:space'?: string | null | undefined;\n    y1?: number | string | null | undefined;\n    y2?: number | string | null | undefined;\n    y?: number | string | null | undefined;\n    yChannelSelector?: string | null | undefined;\n    z?: number | string | null | undefined;\n    zoomAndPan?: string | null | undefined;\n  }\n\n  interface WebViewHTMLAttributes<T> extends HTMLAttributes<T> {\n    allowFullScreen?: boolean | null | undefined;\n    allowpopups?: boolean | null | undefined;\n    autoFocus?: boolean | null | undefined;\n    autosize?: boolean | null | undefined;\n    blinkfeatures?: string | null | undefined;\n    disableblinkfeatures?: string | null | undefined;\n    disableguestresize?: boolean | null | undefined;\n    disablewebsecurity?: boolean | null | undefined;\n    guestinstance?: string | null | undefined;\n    httpreferrer?: string | null | undefined;\n    nodeintegration?: boolean | null | undefined;\n    partition?: string | null | undefined;\n    plugins?: boolean | null | undefined;\n    preload?: string | null | undefined;\n    src?: string | null | undefined;\n    useragent?: string | null | undefined;\n    webpreferences?: string | null | undefined;\n  }\n\n  //\n  // Inferno.DOM\n  // ----------------------------------------------------------------------\n\n  interface InfernoHTML {\n    a: DetailedHTMLFactory<\n      AnchorHTMLAttributes<HTMLAnchorElement>,\n      HTMLAnchorElement\n    >;\n    abbr: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    address: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    area: DetailedHTMLFactory<\n      AreaHTMLAttributes<HTMLAreaElement>,\n      HTMLAreaElement\n    >;\n    article: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    aside: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    audio: DetailedHTMLFactory<\n      AudioHTMLAttributes<HTMLAudioElement>,\n      HTMLAudioElement\n    >;\n    b: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    base: DetailedHTMLFactory<\n      BaseHTMLAttributes<HTMLBaseElement>,\n      HTMLBaseElement\n    >;\n    bdi: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    bdo: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    big: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    blockquote: DetailedHTMLFactory<\n      BlockquoteHTMLAttributes<HTMLQuoteElement>,\n      HTMLQuoteElement\n    >;\n    body: DetailedHTMLFactory<HTMLAttributes<HTMLBodyElement>, HTMLBodyElement>;\n    br: DetailedHTMLFactory<HTMLAttributes<HTMLBRElement>, HTMLBRElement>;\n    button: DetailedHTMLFactory<\n      ButtonHTMLAttributes<HTMLButtonElement>,\n      HTMLButtonElement\n    >;\n    canvas: DetailedHTMLFactory<\n      CanvasHTMLAttributes<HTMLCanvasElement>,\n      HTMLCanvasElement\n    >;\n    caption: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    cite: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    code: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    col: DetailedHTMLFactory<\n      ColHTMLAttributes<HTMLTableColElement>,\n      HTMLTableColElement\n    >;\n    colgroup: DetailedHTMLFactory<\n      ColgroupHTMLAttributes<HTMLTableColElement>,\n      HTMLTableColElement\n    >;\n    data: DetailedHTMLFactory<\n      DataHTMLAttributes<HTMLDataElement>,\n      HTMLDataElement\n    >;\n    datalist: DetailedHTMLFactory<\n      HTMLAttributes<HTMLDataListElement>,\n      HTMLDataListElement\n    >;\n    dd: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    del: DetailedHTMLFactory<DelHTMLAttributes<HTMLModElement>, HTMLModElement>;\n    details: DetailedHTMLFactory<\n      DetailsHTMLAttributes<HTMLDetailsElement>,\n      HTMLDetailsElement\n    >;\n    dfn: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    dialog: DetailedHTMLFactory<\n      DialogHTMLAttributes<HTMLDialogElement>,\n      HTMLDialogElement\n    >;\n    div: DetailedHTMLFactory<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;\n    dl: DetailedHTMLFactory<HTMLAttributes<HTMLDListElement>, HTMLDListElement>;\n    dt: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    em: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    embed: DetailedHTMLFactory<\n      EmbedHTMLAttributes<HTMLEmbedElement>,\n      HTMLEmbedElement\n    >;\n    fieldset: DetailedHTMLFactory<\n      FieldsetHTMLAttributes<HTMLFieldSetElement>,\n      HTMLFieldSetElement\n    >;\n    figcaption: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    figure: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    footer: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    form: DetailedHTMLFactory<\n      FormHTMLAttributes<HTMLFormElement>,\n      HTMLFormElement\n    >;\n    h1: DetailedHTMLFactory<\n      HTMLAttributes<HTMLHeadingElement>,\n      HTMLHeadingElement\n    >;\n    h2: DetailedHTMLFactory<\n      HTMLAttributes<HTMLHeadingElement>,\n      HTMLHeadingElement\n    >;\n    h3: DetailedHTMLFactory<\n      HTMLAttributes<HTMLHeadingElement>,\n      HTMLHeadingElement\n    >;\n    h4: DetailedHTMLFactory<\n      HTMLAttributes<HTMLHeadingElement>,\n      HTMLHeadingElement\n    >;\n    h5: DetailedHTMLFactory<\n      HTMLAttributes<HTMLHeadingElement>,\n      HTMLHeadingElement\n    >;\n    h6: DetailedHTMLFactory<\n      HTMLAttributes<HTMLHeadingElement>,\n      HTMLHeadingElement\n    >;\n    head: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLHeadElement>;\n    header: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    hgroup: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    hr: DetailedHTMLFactory<HTMLAttributes<HTMLHRElement>, HTMLHRElement>;\n    html: DetailedHTMLFactory<\n      HtmlHTMLAttributes<HTMLHtmlElement>,\n      HTMLHtmlElement\n    >;\n    i: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    iframe: DetailedHTMLFactory<\n      IframeHTMLAttributes<HTMLIFrameElement>,\n      HTMLIFrameElement\n    >;\n    img: DetailedHTMLFactory<\n      ImgHTMLAttributes<HTMLImageElement>,\n      HTMLImageElement\n    >;\n    input: DetailedHTMLFactory<\n      InputHTMLAttributes<HTMLInputElement>,\n      HTMLInputElement\n    >;\n    ins: DetailedHTMLFactory<InsHTMLAttributes<HTMLModElement>, HTMLModElement>;\n    kbd: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    keygen: DetailedHTMLFactory<KeygenHTMLAttributes<HTMLElement>, HTMLElement>;\n    label: DetailedHTMLFactory<\n      LabelHTMLAttributes<HTMLLabelElement>,\n      HTMLLabelElement\n    >;\n    legend: DetailedHTMLFactory<\n      HTMLAttributes<HTMLLegendElement>,\n      HTMLLegendElement\n    >;\n    li: DetailedHTMLFactory<LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>;\n    link: DetailedHTMLFactory<\n      LinkHTMLAttributes<HTMLLinkElement>,\n      HTMLLinkElement\n    >;\n    main: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    map: DetailedHTMLFactory<MapHTMLAttributes<HTMLMapElement>, HTMLMapElement>;\n    mark: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    menu: DetailedHTMLFactory<MenuHTMLAttributes<HTMLElement>, HTMLElement>;\n    menuitem: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    meta: DetailedHTMLFactory<\n      MetaHTMLAttributes<HTMLMetaElement>,\n      HTMLMetaElement\n    >;\n    meter: DetailedHTMLFactory<\n      MeterHTMLAttributes<HTMLMeterElement>,\n      HTMLMeterElement\n    >;\n    nav: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    noscript: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    object: DetailedHTMLFactory<\n      ObjectHTMLAttributes<HTMLObjectElement>,\n      HTMLObjectElement\n    >;\n    ol: DetailedHTMLFactory<\n      OlHTMLAttributes<HTMLOListElement>,\n      HTMLOListElement\n    >;\n    optgroup: DetailedHTMLFactory<\n      OptgroupHTMLAttributes<HTMLOptGroupElement>,\n      HTMLOptGroupElement\n    >;\n    option: DetailedHTMLFactory<\n      OptionHTMLAttributes<HTMLOptionElement>,\n      HTMLOptionElement\n    >;\n    output: DetailedHTMLFactory<\n      OutputHTMLAttributes<HTMLOutputElement>,\n      HTMLOutputElement\n    >;\n    p: DetailedHTMLFactory<\n      HTMLAttributes<HTMLParagraphElement>,\n      HTMLParagraphElement\n    >;\n    param: DetailedHTMLFactory<\n      ParamHTMLAttributes<HTMLParamElement>,\n      HTMLParamElement\n    >;\n    picture: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    pre: DetailedHTMLFactory<HTMLAttributes<HTMLPreElement>, HTMLPreElement>;\n    progress: DetailedHTMLFactory<\n      ProgressHTMLAttributes<HTMLProgressElement>,\n      HTMLProgressElement\n    >;\n    q: DetailedHTMLFactory<\n      QuoteHTMLAttributes<HTMLQuoteElement>,\n      HTMLQuoteElement\n    >;\n    rp: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    rt: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    ruby: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    s: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    samp: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    slot: DetailedHTMLFactory<\n      SlotHTMLAttributes<HTMLSlotElement>,\n      HTMLSlotElement\n    >;\n    script: DetailedHTMLFactory<\n      ScriptHTMLAttributes<HTMLScriptElement>,\n      HTMLScriptElement\n    >;\n    section: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    select: DetailedHTMLFactory<\n      SelectHTMLAttributes<HTMLSelectElement>,\n      HTMLSelectElement\n    >;\n    small: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    source: DetailedHTMLFactory<\n      SourceHTMLAttributes<HTMLSourceElement>,\n      HTMLSourceElement\n    >;\n    span: DetailedHTMLFactory<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>;\n    strong: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    style: DetailedHTMLFactory<\n      StyleHTMLAttributes<HTMLStyleElement>,\n      HTMLStyleElement\n    >;\n    sub: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    summary: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    sup: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    table: DetailedHTMLFactory<\n      TableHTMLAttributes<HTMLTableElement>,\n      HTMLTableElement\n    >;\n    template: DetailedHTMLFactory<\n      HTMLAttributes<HTMLTemplateElement>,\n      HTMLTemplateElement\n    >;\n    tbody: DetailedHTMLFactory<\n      HTMLAttributes<HTMLTableSectionElement>,\n      HTMLTableSectionElement\n    >;\n    td: DetailedHTMLFactory<\n      TdHTMLAttributes<HTMLTableDataCellElement>,\n      HTMLTableDataCellElement\n    >;\n    textarea: DetailedHTMLFactory<\n      TextareaHTMLAttributes<HTMLTextAreaElement>,\n      HTMLTextAreaElement\n    >;\n    tfoot: DetailedHTMLFactory<\n      HTMLAttributes<HTMLTableSectionElement>,\n      HTMLTableSectionElement\n    >;\n    th: DetailedHTMLFactory<\n      ThHTMLAttributes<HTMLTableHeaderCellElement>,\n      HTMLTableHeaderCellElement\n    >;\n    thead: DetailedHTMLFactory<\n      HTMLAttributes<HTMLTableSectionElement>,\n      HTMLTableSectionElement\n    >;\n    time: DetailedHTMLFactory<\n      TimeHTMLAttributes<HTMLTimeElement>,\n      HTMLTimeElement\n    >;\n    title: DetailedHTMLFactory<\n      HTMLAttributes<HTMLTitleElement>,\n      HTMLTitleElement\n    >;\n    tr: DetailedHTMLFactory<\n      HTMLAttributes<HTMLTableRowElement>,\n      HTMLTableRowElement\n    >;\n    track: DetailedHTMLFactory<\n      TrackHTMLAttributes<HTMLTrackElement>,\n      HTMLTrackElement\n    >;\n    u: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    ul: DetailedHTMLFactory<HTMLAttributes<HTMLUListElement>, HTMLUListElement>;\n    var: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    video: DetailedHTMLFactory<\n      VideoHTMLAttributes<HTMLVideoElement>,\n      HTMLVideoElement\n    >;\n    wbr: DetailedHTMLFactory<HTMLAttributes<HTMLElement>, HTMLElement>;\n    // webview: DetailedHTMLFactory<WebViewHTMLAttributes<HTMLWebViewElement>, HTMLWebViewElement>;\n  }\n\n  interface InfernoSVG {\n    animate: SVGFactory;\n    circle: SVGFactory;\n    clipPath: SVGFactory;\n    defs: SVGFactory;\n    desc: SVGFactory;\n    ellipse: SVGFactory;\n    feBlend: SVGFactory;\n    feColorMatrix: SVGFactory;\n    feComponentTransfer: SVGFactory;\n    feComposite: SVGFactory;\n    feConvolveMatrix: SVGFactory;\n    feDiffuseLighting: SVGFactory;\n    feDisplacementMap: SVGFactory;\n    feDistantLight: SVGFactory;\n    feDropShadow: SVGFactory;\n    feFlood: SVGFactory;\n    feFuncA: SVGFactory;\n    feFuncB: SVGFactory;\n    feFuncG: SVGFactory;\n    feFuncR: SVGFactory;\n    feGaussianBlur: SVGFactory;\n    feImage: SVGFactory;\n    feMerge: SVGFactory;\n    feMergeNode: SVGFactory;\n    feMorphology: SVGFactory;\n    feOffset: SVGFactory;\n    fePointLight: SVGFactory;\n    feSpecularLighting: SVGFactory;\n    feSpotLight: SVGFactory;\n    feTile: SVGFactory;\n    feTurbulence: SVGFactory;\n    filter: SVGFactory;\n    foreignObject: SVGFactory;\n    g: SVGFactory;\n    image: SVGFactory;\n    line: SVGFactory;\n    linearGradient: SVGFactory;\n    marker: SVGFactory;\n    mask: SVGFactory;\n    metadata: SVGFactory;\n    path: SVGFactory;\n    pattern: SVGFactory;\n    polygon: SVGFactory;\n    polyline: SVGFactory;\n    radialGradient: SVGFactory;\n    rect: SVGFactory;\n    stop: SVGFactory;\n    svg: SVGFactory;\n    switch: SVGFactory;\n    symbol: SVGFactory;\n    text: SVGFactory;\n    textPath: SVGFactory;\n    tspan: SVGFactory;\n    use: SVGFactory;\n    view: SVGFactory;\n  }\n\n  //\n  // Browser Interfaces\n  // https://github.com/nikeee/2048-typescript/blob/master/2048/js/touch.d.ts\n  // ----------------------------------------------------------------------\n\n  interface AbstractView {\n    styleMedia: StyleMedia;\n    document: Document;\n  }\n\n  interface Touch {\n    identifier: number;\n    target: EventTarget;\n    screenX: number;\n    screenY: number;\n    clientX: number;\n    clientY: number;\n    pageX: number;\n    pageY: number;\n  }\n\n  interface TouchList {\n    [index: number]: Touch;\n    length: number;\n    item(index: number): Touch;\n    identifiedTouch(identifier: number): Touch;\n  }\n}\n\ntype Defaultize<P, D> = P extends any\n  ? string extends keyof P\n    ? P\n    : Pick<P, Exclude<keyof P, keyof D>> &\n        Partial<Pick<P, Extract<keyof P, keyof D>>> &\n        Partial<Pick<D, Exclude<keyof D, keyof P>>>\n  : never;\n\ntype InfernoManagedAttributes<C, P> = C extends { defaultProps: infer D }\n  ? Defaultize<P, D>\n  : P;\n\ndeclare global {\n  namespace JSX {\n    interface ElementClass extends IComponent<any, any> {\n      render(nextProps, nextState, nextContext): InfernoNode;\n    }\n    interface ElementAttributesProperty {\n      props: {};\n    }\n    interface ElementChildrenAttribute {\n      children: {};\n    }\n\n    type LibraryManagedAttributes<C, P> = InfernoManagedAttributes<C, P>;\n\n    interface IntrinsicAttributes extends Inferno.Attributes {}\n    interface IntrinsicAttributes extends Inferno.Attributes, Refs<any> {}\n    interface IntrinsicClassAttributes<T> extends Inferno.ClassAttributes<T> {}\n\n    interface IntrinsicElements {\n      // HTML\n      a: Inferno.DetailedHTMLProps<\n        Inferno.AnchorHTMLAttributes<HTMLAnchorElement>,\n        HTMLAnchorElement\n      >;\n      abbr: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      address: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      area: Inferno.DetailedHTMLProps<\n        Inferno.AreaHTMLAttributes<HTMLAreaElement>,\n        HTMLAreaElement\n      >;\n      article: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      aside: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      audio: Inferno.DetailedHTMLProps<\n        Inferno.AudioHTMLAttributes<HTMLAudioElement>,\n        HTMLAudioElement\n      >;\n      b: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      base: Inferno.DetailedHTMLProps<\n        Inferno.BaseHTMLAttributes<HTMLBaseElement>,\n        HTMLBaseElement\n      >;\n      bdi: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      bdo: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      big: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      blockquote: Inferno.DetailedHTMLProps<\n        Inferno.BlockquoteHTMLAttributes<HTMLQuoteElement>,\n        HTMLQuoteElement\n      >;\n      body: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLBodyElement>,\n        HTMLBodyElement\n      >;\n      br: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLBRElement>,\n        HTMLBRElement\n      >;\n      button: Inferno.DetailedHTMLProps<\n        Inferno.ButtonHTMLAttributes<HTMLButtonElement>,\n        HTMLButtonElement\n      >;\n      canvas: Inferno.DetailedHTMLProps<\n        Inferno.CanvasHTMLAttributes<HTMLCanvasElement>,\n        HTMLCanvasElement\n      >;\n      caption: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      cite: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      code: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      col: Inferno.DetailedHTMLProps<\n        Inferno.ColHTMLAttributes<HTMLTableColElement>,\n        HTMLTableColElement\n      >;\n      colgroup: Inferno.DetailedHTMLProps<\n        Inferno.ColgroupHTMLAttributes<HTMLTableColElement>,\n        HTMLTableColElement\n      >;\n      data: Inferno.DetailedHTMLProps<\n        Inferno.DataHTMLAttributes<HTMLDataElement>,\n        HTMLDataElement\n      >;\n      datalist: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLDataListElement>,\n        HTMLDataListElement\n      >;\n      dd: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      del: Inferno.DetailedHTMLProps<\n        Inferno.DelHTMLAttributes<HTMLModElement>,\n        HTMLModElement\n      >;\n      details: Inferno.DetailedHTMLProps<\n        Inferno.DetailsHTMLAttributes<HTMLDetailsElement>,\n        HTMLDetailsElement\n      >;\n      dfn: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      dialog: Inferno.DetailedHTMLProps<\n        Inferno.DialogHTMLAttributes<HTMLDialogElement>,\n        HTMLDialogElement\n      >;\n      div: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLDivElement>,\n        HTMLDivElement\n      >;\n      dl: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLDListElement>,\n        HTMLDListElement\n      >;\n      dt: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      em: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      embed: Inferno.DetailedHTMLProps<\n        Inferno.EmbedHTMLAttributes<HTMLEmbedElement>,\n        HTMLEmbedElement\n      >;\n      fieldset: Inferno.DetailedHTMLProps<\n        Inferno.FieldsetHTMLAttributes<HTMLFieldSetElement>,\n        HTMLFieldSetElement\n      >;\n      figcaption: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      figure: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      footer: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      form: Inferno.DetailedHTMLProps<\n        Inferno.FormHTMLAttributes<HTMLFormElement>,\n        HTMLFormElement\n      >;\n      h1: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLHeadingElement>,\n        HTMLHeadingElement\n      >;\n      h2: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLHeadingElement>,\n        HTMLHeadingElement\n      >;\n      h3: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLHeadingElement>,\n        HTMLHeadingElement\n      >;\n      h4: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLHeadingElement>,\n        HTMLHeadingElement\n      >;\n      h5: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLHeadingElement>,\n        HTMLHeadingElement\n      >;\n      h6: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLHeadingElement>,\n        HTMLHeadingElement\n      >;\n      head: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLHeadElement>,\n        HTMLHeadElement\n      >;\n      header: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      hgroup: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      hr: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLHRElement>,\n        HTMLHRElement\n      >;\n      html: Inferno.DetailedHTMLProps<\n        Inferno.HtmlHTMLAttributes<HTMLHtmlElement>,\n        HTMLHtmlElement\n      >;\n      i: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      iframe: Inferno.DetailedHTMLProps<\n        Inferno.IframeHTMLAttributes<HTMLIFrameElement>,\n        HTMLIFrameElement\n      >;\n      img: Inferno.DetailedHTMLProps<\n        Inferno.ImgHTMLAttributes<HTMLImageElement>,\n        HTMLImageElement\n      >;\n      input: Inferno.DetailedHTMLProps<\n        Inferno.InputHTMLAttributes<HTMLInputElement>,\n        HTMLInputElement\n      >;\n      ins: Inferno.DetailedHTMLProps<\n        Inferno.InsHTMLAttributes<HTMLModElement>,\n        HTMLModElement\n      >;\n      kbd: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      keygen: Inferno.DetailedHTMLProps<\n        Inferno.KeygenHTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      label: Inferno.DetailedHTMLProps<\n        Inferno.LabelHTMLAttributes<HTMLLabelElement>,\n        HTMLLabelElement\n      >;\n      legend: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLLegendElement>,\n        HTMLLegendElement\n      >;\n      li: Inferno.DetailedHTMLProps<\n        Inferno.LiHTMLAttributes<HTMLLIElement>,\n        HTMLLIElement\n      >;\n      link: Inferno.DetailedHTMLProps<\n        Inferno.LinkHTMLAttributes<HTMLLinkElement>,\n        HTMLLinkElement\n      >;\n      main: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      map: Inferno.DetailedHTMLProps<\n        Inferno.MapHTMLAttributes<HTMLMapElement>,\n        HTMLMapElement\n      >;\n      mark: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      media: Inferno.DetailedHTMLProps<\n        Inferno.MediaHTMLAttributes<HTMLMediaElement>,\n        HTMLMediaElement\n      >;\n      menu: Inferno.DetailedHTMLProps<\n        Inferno.MenuHTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      menuitem: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      meta: Inferno.DetailedHTMLProps<\n        Inferno.MetaHTMLAttributes<HTMLMetaElement>,\n        HTMLMetaElement\n      >;\n      meter: Inferno.DetailedHTMLProps<\n        Inferno.MeterHTMLAttributes<HTMLMeterElement>,\n        HTMLMeterElement\n      >;\n      nav: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      noindex: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      noscript: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      object: Inferno.DetailedHTMLProps<\n        Inferno.ObjectHTMLAttributes<HTMLObjectElement>,\n        HTMLObjectElement\n      >;\n      ol: Inferno.DetailedHTMLProps<\n        Inferno.OlHTMLAttributes<HTMLOListElement>,\n        HTMLOListElement\n      >;\n      optgroup: Inferno.DetailedHTMLProps<\n        Inferno.OptgroupHTMLAttributes<HTMLOptGroupElement>,\n        HTMLOptGroupElement\n      >;\n      option: Inferno.DetailedHTMLProps<\n        Inferno.OptionHTMLAttributes<HTMLOptionElement>,\n        HTMLOptionElement\n      >;\n      output: Inferno.DetailedHTMLProps<\n        Inferno.OutputHTMLAttributes<HTMLOutputElement>,\n        HTMLOutputElement\n      >;\n      p: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLParagraphElement>,\n        HTMLParagraphElement\n      >;\n      param: Inferno.DetailedHTMLProps<\n        Inferno.ParamHTMLAttributes<HTMLParamElement>,\n        HTMLParamElement\n      >;\n      picture: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      pre: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLPreElement>,\n        HTMLPreElement\n      >;\n      progress: Inferno.DetailedHTMLProps<\n        Inferno.ProgressHTMLAttributes<HTMLProgressElement>,\n        HTMLProgressElement\n      >;\n      q: Inferno.DetailedHTMLProps<\n        Inferno.QuoteHTMLAttributes<HTMLQuoteElement>,\n        HTMLQuoteElement\n      >;\n      rp: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      rt: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      ruby: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      s: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      samp: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      slot: Inferno.DetailedHTMLProps<\n        Inferno.SlotHTMLAttributes<HTMLSlotElement>,\n        HTMLSlotElement\n      >;\n      script: Inferno.DetailedHTMLProps<\n        Inferno.ScriptHTMLAttributes<HTMLScriptElement>,\n        HTMLScriptElement\n      >;\n      section: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      select: Inferno.DetailedHTMLProps<\n        Inferno.SelectHTMLAttributes<HTMLSelectElement>,\n        HTMLSelectElement\n      >;\n      small: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      source: Inferno.DetailedHTMLProps<\n        Inferno.SourceHTMLAttributes<HTMLSourceElement>,\n        HTMLSourceElement\n      >;\n      span: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLSpanElement>,\n        HTMLSpanElement\n      >;\n      strong: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      style: Inferno.DetailedHTMLProps<\n        Inferno.StyleHTMLAttributes<HTMLStyleElement>,\n        HTMLStyleElement\n      >;\n      sub: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      summary: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      sup: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      table: Inferno.DetailedHTMLProps<\n        Inferno.TableHTMLAttributes<HTMLTableElement>,\n        HTMLTableElement\n      >;\n      template: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLTemplateElement>,\n        HTMLTemplateElement\n      >;\n      tbody: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLTableSectionElement>,\n        HTMLTableSectionElement\n      >;\n      td: Inferno.DetailedHTMLProps<\n        Inferno.TdHTMLAttributes<HTMLTableDataCellElement>,\n        HTMLTableDataCellElement\n      >;\n      textarea: Inferno.DetailedHTMLProps<\n        Inferno.TextareaHTMLAttributes<HTMLTextAreaElement>,\n        HTMLTextAreaElement\n      >;\n      tfoot: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLTableSectionElement>,\n        HTMLTableSectionElement\n      >;\n      th: Inferno.DetailedHTMLProps<\n        Inferno.ThHTMLAttributes<HTMLTableHeaderCellElement>,\n        HTMLTableHeaderCellElement\n      >;\n      thead: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLTableSectionElement>,\n        HTMLTableSectionElement\n      >;\n      time: Inferno.DetailedHTMLProps<\n        Inferno.TimeHTMLAttributes<HTMLTimeElement>,\n        HTMLTimeElement\n      >;\n      title: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLTitleElement>,\n        HTMLTitleElement\n      >;\n      tr: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLTableRowElement>,\n        HTMLTableRowElement\n      >;\n      track: Inferno.DetailedHTMLProps<\n        Inferno.TrackHTMLAttributes<HTMLTrackElement>,\n        HTMLTrackElement\n      >;\n      u: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      ul: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLUListElement>,\n        HTMLUListElement\n      >;\n      var: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      video: Inferno.DetailedHTMLProps<\n        Inferno.VideoHTMLAttributes<HTMLVideoElement>,\n        HTMLVideoElement\n      >;\n      wbr: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<HTMLElement>,\n        HTMLElement\n      >;\n      // webview: Inferno.DetailedHTMLProps<Inferno.WebViewHTMLAttributes<HTMLWebViewElement>, HTMLWebViewElement>;\n\n      // SVG\n      svg: Inferno.SVGProps<SVGSVGElement>;\n\n      animate: Inferno.SVGProps<SVGAnimateElement>;\n      animateMotion: Inferno.SVGProps<SVGElement>;\n      animateTransform: Inferno.SVGProps<SVGAnimateTransformElement>;\n      circle: Inferno.SVGProps<SVGCircleElement>;\n      clipPath: Inferno.SVGProps<SVGClipPathElement>;\n      defs: Inferno.SVGProps<SVGDefsElement>;\n      desc: Inferno.SVGProps<SVGDescElement>;\n      ellipse: Inferno.SVGProps<SVGEllipseElement>;\n      feBlend: Inferno.SVGProps<SVGFEBlendElement>;\n      feColorMatrix: Inferno.SVGProps<SVGFEColorMatrixElement>;\n      feComponentTransfer: Inferno.SVGProps<SVGFEComponentTransferElement>;\n      feComposite: Inferno.SVGProps<SVGFECompositeElement>;\n      feConvolveMatrix: Inferno.SVGProps<SVGFEConvolveMatrixElement>;\n      feDiffuseLighting: Inferno.SVGProps<SVGFEDiffuseLightingElement>;\n      feDisplacementMap: Inferno.SVGProps<SVGFEDisplacementMapElement>;\n      feDistantLight: Inferno.SVGProps<SVGFEDistantLightElement>;\n      feDropShadow: Inferno.SVGProps<SVGFEDropShadowElement>;\n      feFlood: Inferno.SVGProps<SVGFEFloodElement>;\n      feFuncA: Inferno.SVGProps<SVGFEFuncAElement>;\n      feFuncB: Inferno.SVGProps<SVGFEFuncBElement>;\n      feFuncG: Inferno.SVGProps<SVGFEFuncGElement>;\n      feFuncR: Inferno.SVGProps<SVGFEFuncRElement>;\n      feGaussianBlur: Inferno.SVGProps<SVGFEGaussianBlurElement>;\n      feImage: Inferno.SVGProps<SVGFEImageElement>;\n      feMerge: Inferno.SVGProps<SVGFEMergeElement>;\n      feMergeNode: Inferno.SVGProps<SVGFEMergeNodeElement>;\n      feMorphology: Inferno.SVGProps<SVGFEMorphologyElement>;\n      feOffset: Inferno.SVGProps<SVGFEOffsetElement>;\n      fePointLight: Inferno.SVGProps<SVGFEPointLightElement>;\n      feSpecularLighting: Inferno.SVGProps<SVGFESpecularLightingElement>;\n      feSpotLight: Inferno.SVGProps<SVGFESpotLightElement>;\n      feTile: Inferno.SVGProps<SVGFETileElement>;\n      feTurbulence: Inferno.SVGProps<SVGFETurbulenceElement>;\n      filter: Inferno.SVGProps<SVGFilterElement>;\n      foreignObject: Inferno.SVGProps<SVGForeignObjectElement>;\n      g: Inferno.SVGProps<SVGGElement>;\n      image: Inferno.SVGProps<SVGImageElement>;\n      line: Inferno.SVGProps<SVGLineElement>;\n      linearGradient: Inferno.SVGProps<SVGLinearGradientElement>;\n      marker: Inferno.SVGProps<SVGMarkerElement>;\n      mask: Inferno.SVGProps<SVGMaskElement>;\n      metadata: Inferno.SVGProps<SVGMetadataElement>;\n      mpath: Inferno.SVGProps<SVGElement>;\n      path: Inferno.SVGProps<SVGPathElement>;\n      pattern: Inferno.SVGProps<SVGPatternElement>;\n      polygon: Inferno.SVGProps<SVGPolygonElement>;\n      polyline: Inferno.SVGProps<SVGPolylineElement>;\n      radialGradient: Inferno.SVGProps<SVGRadialGradientElement>;\n      rect: Inferno.SVGProps<SVGRectElement>;\n      stop: Inferno.SVGProps<SVGStopElement>;\n      switch: Inferno.SVGProps<SVGSwitchElement>;\n      symbol: Inferno.SVGProps<SVGSymbolElement>;\n      text: Inferno.SVGProps<SVGTextElement>;\n      textPath: Inferno.SVGProps<SVGTextPathElement>;\n      tspan: Inferno.SVGProps<SVGTSpanElement>;\n      use: Inferno.SVGProps<SVGUseElement>;\n      view: Inferno.SVGProps<SVGViewElement>;\n\n      // MathML\n      maction: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      math: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      menclose: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      merror: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mfenced: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mfrac: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mi: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mmultiscripts: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mn: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mo: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mover: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mpadded: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mphantom: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mroot: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mrow: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      ms: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mspace: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      msqrt: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mstyle: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      msub: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      msubsup: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      msup: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mtable: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mtd: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mtext: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      mtr: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      munder: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      munderover: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n      semantics: Inferno.DetailedHTMLProps<\n        Inferno.HTMLAttributes<MathMLElement>,\n        MathMLElement\n      >;\n    }\n  }\n\n  var SKIP_INFERNO_WARNINGS: string;\n}\n"
  },
  {
    "path": "packages/inferno/src/core/validate.ts",
    "content": "import type { VNode } from './types';\nimport {\n  isArray,\n  isInvalid,\n  isNullOrUndef,\n  isNumber,\n  isStringOrNumber,\n  throwError\n} from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport { getComponentName } from '../DOM/utils/common';\n\nfunction getTagName(input): string {\n  let tagName;\n\n  if (isArray(input)) {\n    const arrayText =\n      input.length > 3\n        ? input.slice(0, 3).toString() + ',...'\n        : input.toString();\n\n    tagName = 'Array(' + arrayText + ')';\n  } else if (isStringOrNumber(input)) {\n    tagName = 'Text(' + input + ')';\n  } else if (isInvalid(input)) {\n    tagName = 'InvalidVNode(' + input + ')';\n  } else {\n    const flags = input?.flags;\n\n    if (!isNumber(flags)) {\n      try {\n        tagName = `Object(${JSON.stringify(input)})`;\n      } catch {\n        tagName = `Object(${String(input)})`;\n      }\n\n      return '>> ' + tagName + '\\n';\n    }\n\n    if (flags & VNodeFlags.Element) {\n      tagName = `<${input.type}${\n        input.className ? ' class=\"' + input.className + '\"' : ''\n      }>`;\n    } else if (flags & VNodeFlags.Text) {\n      tagName = `Text(${input.children})`;\n    } else if (flags & VNodeFlags.Portal) {\n      tagName = `Portal*`;\n    } else {\n      tagName = `<${getComponentName(input.type)} />`;\n    }\n  }\n\n  return '>> ' + tagName + '\\n';\n}\n\nfunction DEV_VALIDATE_KEYS(vNodeTree, childKeys): string | null {\n  if ((childKeys & ChildFlags.HasNonKeyedChildren) !== 0) {\n    return null;\n  }\n\n  const foundKeys: Record<string, boolean> = {};\n  const forceKeyed = (childKeys & ChildFlags.HasKeyedChildren) !== 0;\n\n  let foundKeyCount = 0;\n\n  for (let i = 0, len = vNodeTree.length; i < len; ++i) {\n    const childNode = vNodeTree[i];\n\n    if (isArray(childNode)) {\n      return (\n        'Encountered ARRAY in mount, array must be flattened, or normalize used. Location: \\n' +\n        getTagName(childNode)\n      );\n    }\n\n    if (isInvalid(childNode)) {\n      if (forceKeyed) {\n        return (\n          'Encountered invalid node when preparing to keyed algorithm. Location: \\n' +\n          getTagName(childNode)\n        );\n      } else if (foundKeyCount !== 0) {\n        return (\n          'Encountered invalid node with mixed keys. Location: \\n' +\n          getTagName(childNode)\n        );\n      }\n      continue;\n    }\n    if (typeof (childNode as VNode) === 'object') {\n      if (childNode.isValidated) {\n        continue;\n      }\n      childNode.isValidated = true;\n    }\n\n    // Key can be undefined, null too. But typescript complains for no real reason\n    const key: string | number = childNode.key as string | number;\n\n    if (!isNullOrUndef(key) && !isStringOrNumber(key)) {\n      return (\n        'Encountered child vNode where key property is not string or number. Location: \\n' +\n        getTagName(childNode)\n      );\n    }\n\n    const children = childNode.children;\n    const childFlags = childNode.childFlags;\n    if (!isInvalid(children)) {\n      let val;\n      if (childFlags & ChildFlags.MultipleChildren) {\n        val = DEV_VALIDATE_KEYS(\n          children,\n          (childFlags & ChildFlags.HasKeyedChildren) !== 0,\n        );\n      } else if (childFlags === ChildFlags.HasVNodeChildren) {\n        val = DEV_VALIDATE_KEYS([children], false);\n      }\n      if (val) {\n        val += getTagName(childNode);\n\n        return val;\n      }\n    }\n    if (forceKeyed && isNullOrUndef(key)) {\n      return (\n        'Encountered child without key during keyed algorithm. If this error points to Array make sure children is flat list. Location: \\n' +\n        getTagName(childNode)\n      );\n    } else if (isNullOrUndef(key)) {\n      if (foundKeyCount !== 0) {\n        return (\n          'Encountered children with key missing. Location: \\n' +\n          getTagName(childNode)\n        );\n      }\n      continue;\n    }\n    if (foundKeys[key]) {\n      return (\n        'Encountered two children with same key: {' +\n        key +\n        '}. Location: \\n' +\n        getTagName(childNode)\n      );\n    }\n    foundKeys[key] = true;\n    foundKeyCount++;\n  }\n\n  return null;\n}\n\nexport function validateVNodeElementChildren(vNode): void {\n  if (process.env.NODE_ENV !== 'production') {\n    if (vNode.childFlags === ChildFlags.HasInvalidChildren) {\n      return;\n    }\n    if (vNode.flags & VNodeFlags.InputElement) {\n      throwError(\"input elements can't have children.\");\n    }\n    if (vNode.flags & VNodeFlags.TextareaElement) {\n      throwError(\"textarea elements can't have children.\");\n    }\n    if (vNode.flags & VNodeFlags.Element) {\n      const tag = vNode.type.toLowerCase();\n\n      switch (tag) {\n        case 'media':\n        case 'area':\n        case 'base':\n        case 'br':\n        case 'col':\n        case 'command':\n        case 'embed':\n        case 'hr':\n        case 'img':\n        case 'input':\n        case 'keygen':\n        case 'link':\n        case 'meta':\n        case 'param':\n        case 'source':\n        case 'track':\n        case 'wbr':\n          throwError(`${tag} elements can't have children.`);\n          break;\n        default:\n          break;\n      }\n    }\n  }\n}\n\nexport function validateKeys(vNode): void {\n  if (process.env.NODE_ENV !== 'production') {\n    // Checks if there is any key missing or duplicate keys\n    if (\n      !vNode.isValidated &&\n      vNode.children &&\n      vNode.flags & VNodeFlags.Element\n    ) {\n      const error = DEV_VALIDATE_KEYS(\n        Array.isArray(vNode.children) ? vNode.children : [vNode.children],\n        vNode.childFlags\n      );\n\n      if (error) {\n        throwError(error + getTagName(vNode));\n      }\n    }\n    vNode.isValidated = true;\n  }\n}\n\nfunction getChildFlagsName(childFlags: ChildFlags): string {\n  switch (childFlags) {\n    case ChildFlags.HasInvalidChildren:\n      return 'ChildFlags.HasInvalidChildren';\n    case ChildFlags.HasVNodeChildren:\n      return 'ChildFlags.HasVNodeChildren';\n    case ChildFlags.HasNonKeyedChildren:\n      return 'ChildFlags.HasNonKeyedChildren';\n    case ChildFlags.HasKeyedChildren:\n      return 'ChildFlags.HasKeyedChildren';\n    case ChildFlags.HasTextChildren:\n      return 'ChildFlags.HasTextChildren';\n    case ChildFlags.UnknownChildren:\n      return 'ChildFlags.UnknownChildren';\n    default:\n      return `ChildFlags.Unknown(${childFlags})`;\n  }\n}\n\nexport function validateChildFlags(vNode: VNode): void {\n  if (process.env.NODE_ENV === 'production') {\n    return;\n  }\n\n  const childFlags = vNode.childFlags;\n  const children = vNode.children as any;\n  const parentTag = getTagName(vNode);\n\n  switch (childFlags) {\n    case ChildFlags.UnknownChildren:\n    case ChildFlags.HasInvalidChildren:\n      return;\n    case ChildFlags.HasTextChildren:\n      if (isStringOrNumber(children)) {\n        return;\n      }\n      if (\n        children &&\n        isNumber(children.flags) &&\n        children.flags & VNodeFlags.Text\n      ) {\n        throwError(\n          `${getChildFlagsName(childFlags)} expects children to be a bare string, not a Text VNode. Location: \\n${getTagName(children)}${parentTag}`,\n        );\n      }\n      throwError(\n        `${getChildFlagsName(childFlags)} expects children to be a string. Location: \\n${getTagName(children)}${parentTag}`,\n      );\n      return;\n    case ChildFlags.HasVNodeChildren:\n      if (isInvalid(children) || isArray(children) || isStringOrNumber(children)) {\n        throwError(\n          `${getChildFlagsName(childFlags)} expects children to be a VNode. Location: \\n${getTagName(children)}${parentTag}`,\n        );\n      }\n      throwIfObjectIsNotVNode(children);\n      return;\n    case ChildFlags.HasNonKeyedChildren:\n    case ChildFlags.HasKeyedChildren:\n      if (!isArray(children)) {\n        throwError(\n          `${getChildFlagsName(childFlags)} expects children to be an array of VNodes. Location: \\n${getTagName(children)}${parentTag}`,\n        );\n      }\n\n      for (let i = 0; i < children.length; i++) {\n        if (!(i in children)) {\n          throwError(\n            `${getChildFlagsName(childFlags)} expects children to be a flat array without holes; found a hole at index ${i}. Location: \\n${parentTag}`,\n          );\n        }\n\n        const child = children[i];\n        if (isArray(child)) {\n          throwError(\n            `${getChildFlagsName(childFlags)} expects children to be a flat array; found a nested array at index ${i}. Location: \\n${getTagName(child)}${parentTag}`,\n          );\n        }\n        if (isInvalid(child)) {\n          throwError(\n            `${getChildFlagsName(childFlags)} expects children to be VNodes; found invalid child at index ${i}. Location: \\n${getTagName(child)}${parentTag}`,\n          );\n        }\n        if (isStringOrNumber(child)) {\n          throwError(\n            `${getChildFlagsName(childFlags)} expects children to be VNodes; found text at index ${i}. Location: \\n${getTagName(child)}${parentTag}`,\n          );\n        }\n\n        throwIfObjectIsNotVNode(child);\n\n        if (childFlags === ChildFlags.HasKeyedChildren) {\n          if (isNullOrUndef(child.key)) {\n            throwError(\n              `${getChildFlagsName(childFlags)} expects all children to have keys; missing key at index ${i}. Location: \\n${getTagName(child)}${parentTag}`,\n            );\n          }\n        }\n      }\n      return;\n    default:\n      return;\n  }\n}\n\nexport function throwIfObjectIsNotVNode(input): void {\n  if (!isNumber(input.flags)) {\n    throwError(\n      `normalization received an object that's not a valid VNode, you should stringify it first or fix createVNode flags. Object: \"${JSON.stringify(\n        input,\n      )}\".`,\n    );\n  }\n}\n"
  },
  {
    "path": "packages/inferno/src/index.ts",
    "content": "import { warning } from 'inferno-shared';\nimport {\n  createComponentVNode,\n  createFragment,\n  createPortal,\n  createTextVNode,\n  createVNode,\n  directClone,\n  getFlagsForElementVnode,\n  normalizeProps,\n  normalizeRoot,\n} from './core/implementation';\nimport { linkEvent } from './DOM/events/linkEvent';\nimport { renderInternal, createRenderer, render } from './DOM/rendering';\nimport {\n  AnimationQueues,\n  EMPTY_OBJ,\n  findDOMFromVNode,\n  Fragment,\n  options,\n} from './DOM/utils/common';\nimport { Component, type ComponentType, rerender } from './core/component';\nimport { mountProps } from './DOM/props';\nimport {\n  createClassComponentInstance,\n  renderFunctionalComponent,\n} from './DOM/utils/componentUtil';\nimport {\n  mount,\n  mountClassComponentCallbacks,\n  mountElement,\n  mountFunctionalComponentCallbacks,\n} from './DOM/mounting';\nimport { createRef, forwardRef, mountRef } from './core/refs';\nexport * from './core/types';\n\nif (process.env.NODE_ENV !== 'production') {\n  const skipWarnings =\n    typeof SKIP_INFERNO_WARNINGS !== 'undefined' ||\n    (typeof process === 'object' &&\n      (process.env?.SKIP_INFERNO_WARNINGS !== undefined ||\n        process.env?.JEST_WORKER_ID !== undefined));\n\n  if (!skipWarnings) {\n    const testFunc = function testFn() {};\n\n    if (\n      !((testFunc as Function).name || testFunc.toString()).includes('testFn')\n    ) {\n      warning(\n        \"It looks like you're using a minified copy of the development build \" +\n          'of Inferno. When deploying Inferno apps to production, make sure to use ' +\n          'the production build which skips development warnings and is faster. ' +\n          'See https://infernojs.org for more details.',\n      );\n    }\n  }\n}\n\nconst version = process.env.INFERNO_VERSION;\n\nexport {\n  AnimationQueues,\n  Component,\n  type ComponentType,\n  Fragment,\n  EMPTY_OBJ,\n  createComponentVNode,\n  createFragment,\n  createPortal,\n  createRef,\n  createRenderer,\n  createTextVNode,\n  createVNode,\n  forwardRef,\n  directClone,\n  findDOMFromVNode,\n  getFlagsForElementVnode,\n  linkEvent,\n  normalizeProps,\n  options,\n  render,\n  rerender,\n  version,\n  // Internal methods, used by hydration\n  createClassComponentInstance as _CI,\n  normalizeRoot as _HI, // used by inferno-mobx\n  mount as _M,\n  mountClassComponentCallbacks as _MCCC,\n  mountElement as _ME,\n  mountFunctionalComponentCallbacks as _MFCC,\n  mountRef as _MR,\n  mountProps as _MP,\n  renderInternal,\n  renderFunctionalComponent as _RFC,\n};\n"
  },
  {
    "path": "packages/inferno-animation/__tests__/animatedAllComponent.spec.tsx",
    "content": "import { type InfernoNode, render } from 'inferno';\nimport { renderToString } from 'inferno-server';\nimport {\n  AnimatedAllComponent,\n  componentDidAppear,\n  componentWillDisappear,\n  componentWillMove,\n} from 'inferno-animation';\n\ndescribe('inferno-animation AnimatedAllComponent', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  function waitForAnimationAndContinue(condition, callback, arg1?: any): void {\n    if (container.textContent !== condition) {\n      setTimeout(\n        waitForAnimationAndContinue.bind(null, condition, callback, arg1),\n        10,\n      );\n      return;\n    }\n\n    callback(arg1);\n  }\n\n  function afterEachClear(done): void {\n    container.innerHTML = '';\n    document.body.removeChild(container);\n    done();\n  }\n\n  afterEach(function (done) {\n    render(null, container);\n    waitForAnimationAndContinue('', afterEachClear, done);\n  });\n\n  it('should render class component extending AnimatedAllComponent into DOM', () => {\n    class MyComponent extends AnimatedAllComponent<any, any> {\n      public render({ children }): InfernoNode {\n        return <div>{children}</div>;\n      }\n    }\n\n    render(<MyComponent>1</MyComponent>, container);\n    expect(container.textContent).toBe('1');\n  });\n\n  it('should remove class component extending AnimatedAllComponent from DOM', (done) => {\n    class My extends AnimatedAllComponent<any, any> {\n      public render({ children }): InfernoNode {\n        return <div>{children}</div>;\n      }\n    }\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#2\">2</My>\n        <My key=\"#3\">3</My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#3\">3</My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedAllComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n\n    waitForAnimationAndContinue('13', function () {\n      render(\n        <div>\n          <My key=\"#1\">1</My>\n          <My key=\"#4\">4</My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('14', function () {\n        done();\n      });\n    });\n  });\n\n  it('should move class component extending AnimatedAllComponent from DOM', (done) => {\n    class My extends AnimatedAllComponent<any, any> {\n      public render({ children }): InfernoNode {\n        return <div>{children}</div>;\n      }\n    }\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#2\">2</My>\n        <My key=\"#3\">3</My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#3\">3</My>\n        <My key=\"#2\">2</My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedAllComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n    // Disappear animations complete async\n\n    waitForAnimationAndContinue('132', function () {\n      render(\n        <div>\n          <My key=\"#4\">4</My>\n          <My key=\"#1\">1</My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('41', function () {\n        render(null, container);\n        done();\n      });\n    });\n  });\n\n  it('should render class component extending AnimatedAllComponent to a string', () => {\n    class MyComponent extends AnimatedAllComponent<any, any> {\n      public render({ children }): InfernoNode {\n        return <div>{children}</div>;\n      }\n    }\n\n    const outputStr = renderToString(<MyComponent>1</MyComponent>);\n    expect(outputStr).toBe('<div>1</div>');\n  });\n});\n\ndescribe('inferno-animation animated functional component', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  function waitForAnimationAndContinue(condition, callback, arg1?): void {\n    if (container.textContent !== condition) {\n      setTimeout(\n        waitForAnimationAndContinue.bind(null, condition, callback, arg1),\n        10,\n      );\n      return;\n    }\n\n    callback(arg1);\n  }\n\n  function afterEachClear(done): void {\n    container.innerHTML = '';\n    document.body.removeChild(container);\n    done();\n  }\n\n  afterEach(function (done) {\n    render(null, container);\n    waitForAnimationAndContinue('', afterEachClear, done);\n  });\n\n  it('should render functional component extending AnimatedAllComponent into DOM', () => {\n    const MyComponent = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    render(\n      <MyComponent\n        onComponentDidAppear={componentDidAppear}\n        onComponentWillDisappear={componentWillDisappear}\n        onComponentWillMove={componentWillMove}\n      >\n        1\n      </MyComponent>,\n      container,\n    );\n    expect(container.textContent).toBe('1');\n  });\n\n  it('should remove functional component extending AnimatedAllComponent from DOM', (done) => {\n    const My = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    const anim = {\n      onComponentDidAppear: componentDidAppear,\n      onComponentWillDisappear: componentWillDisappear,\n      onComponentWillMove: componentWillMove,\n    };\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#2\" {...anim}>\n          2\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedAllComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n\n    waitForAnimationAndContinue('13', function () {\n      render(\n        <div>\n          <My key=\"#1\" {...anim}>\n            1\n          </My>\n          <My key=\"#4\" {...anim}>\n            4\n          </My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('14', function () {\n        done();\n      });\n    });\n  });\n\n  it('should move functional component extending AnimatedAllComponent from DOM', (done) => {\n    const My = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    const anim = {\n      onComponentDidAppear: componentDidAppear,\n      onComponentWillDisappear: componentWillDisappear,\n      onComponentWillMove: componentWillMove,\n    };\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#2\" {...anim}>\n          2\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n        <My key=\"#2\" {...anim}>\n          2\n        </My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedAllComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n    // Disappear animations complete async\n\n    waitForAnimationAndContinue('132', function () {\n      render(\n        <div>\n          <My key=\"#4\" {...anim}>\n            4\n          </My>\n          <My key=\"#1\" {...anim}>\n            1\n          </My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('41', function () {\n        render(null, container);\n        done();\n      });\n    });\n  });\n\n  it('should render class component extending AnimatedAllComponent to a string', () => {\n    const MyComponent = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    const anim = {\n      onComponentDidAppear: componentDidAppear,\n      onComponentWillDisappear: componentWillDisappear,\n      onComponentWillMove: componentWillMove,\n    };\n\n    const outputStr = renderToString(<MyComponent {...anim}>1</MyComponent>);\n    expect(outputStr).toBe('<div>1</div>');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-animation/__tests__/animatedComponent.spec.tsx",
    "content": "import { type InfernoNode, render } from 'inferno';\nimport { renderToString } from 'inferno-server';\nimport {\n  AnimatedComponent,\n  componentDidAppear,\n  componentWillDisappear,\n} from 'inferno-animation';\n\ndescribe('inferno-animation AnimatedComponent', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  function waitForAnimationAndContinue(condition, callback, arg1?): void {\n    if (container.textContent !== condition) {\n      setTimeout(\n        waitForAnimationAndContinue.bind(null, condition, callback, arg1),\n        10,\n      );\n      return;\n    }\n\n    callback(arg1);\n  }\n\n  function afterEachClear(done): void {\n    container.innerHTML = '';\n    document.body.removeChild(container);\n    done();\n  }\n\n  afterEach(function (done) {\n    render(null, container);\n    waitForAnimationAndContinue('', afterEachClear, done);\n  });\n\n  it('should render class component extending AnimatedComponent into DOM', () => {\n    class MyComponent extends AnimatedComponent<any, any> {\n      public render({ children }): InfernoNode {\n        return <div>{children}</div>;\n      }\n    }\n\n    render(<MyComponent>1</MyComponent>, container);\n    expect(container.textContent).toBe('1');\n  });\n\n  it('should remove class component extending AnimatedComponent from DOM', (done) => {\n    class My extends AnimatedComponent<any, any> {\n      public render({ children }): void {\n        return <div>{children}</div>;\n      }\n    }\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#2\">2</My>\n        <My key=\"#3\">3</My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#3\">3</My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n\n    waitForAnimationAndContinue('13', function () {\n      render(\n        <div>\n          <My key=\"#1\">1</My>\n          <My key=\"#4\">4</My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('14', function () {\n        done();\n      });\n    });\n  });\n\n  it('should move class component extending AnimatedComponent from DOM', (done) => {\n    class My extends AnimatedComponent<any, any> {\n      public render({ children }): void {\n        return <div>{children}</div>;\n      }\n    }\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#2\">2</My>\n        <My key=\"#3\">3</My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#3\">3</My>\n        <My key=\"#2\">2</My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n    // Disappear animations complete async\n\n    waitForAnimationAndContinue('132', function () {\n      render(\n        <div>\n          <My key=\"#4\">4</My>\n          <My key=\"#1\">1</My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('41', function () {\n        render(null, container);\n        done();\n      });\n    });\n  });\n\n  it('should render class component extending AnimatedComponent to a string', () => {\n    class MyComponent extends AnimatedComponent<any, any> {\n      public render({ children }): InfernoNode {\n        return <div>{children}</div>;\n      }\n    }\n\n    const outputStr = renderToString(<MyComponent>1</MyComponent>);\n    expect(outputStr).toBe('<div>1</div>');\n  });\n});\n\ndescribe('inferno-animation animated functional component', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  function waitForAnimationAndContinue(condition, callback, arg1?): void {\n    if (container.textContent !== condition) {\n      setTimeout(\n        waitForAnimationAndContinue.bind(null, condition, callback, arg1),\n        10,\n      );\n      return;\n    }\n\n    callback(arg1);\n  }\n\n  function afterEachClear(done): void {\n    container.innerHTML = '';\n    document.body.removeChild(container);\n    done();\n  }\n\n  afterEach(function (done) {\n    render(null, container);\n    waitForAnimationAndContinue('', afterEachClear, done);\n  });\n\n  it('should render class component extending AnimatedComponent into DOM', () => {\n    const MyComponent = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    render(\n      <MyComponent\n        onComponentDidAppear={componentDidAppear}\n        onComponentWillDisappear={componentWillDisappear}\n      >\n        1\n      </MyComponent>,\n      container,\n    );\n    expect(container.textContent).toBe('1');\n  });\n\n  it('should remove class component extending AnimatedComponent from DOM', (done) => {\n    const My = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    const anim = {\n      onComponentDidAppear: componentDidAppear,\n      onComponentWillDisappear: componentWillDisappear,\n    };\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#2\" {...anim}>\n          2\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n\n    waitForAnimationAndContinue('13', function () {\n      render(\n        <div>\n          <My key=\"#1\" {...anim}>\n            1\n          </My>\n          <My key=\"#4\" {...anim}>\n            4\n          </My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('14', function () {\n        done();\n      });\n    });\n  });\n\n  it('should move class component extending AnimatedComponent from DOM', (done) => {\n    const My = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    const anim = {\n      onComponentDidAppear: componentDidAppear,\n      onComponentWillDisappear: componentWillDisappear,\n    };\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#2\" {...anim}>\n          2\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n        <My key=\"#2\" {...anim}>\n          2\n        </My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n    // Disappear animations complete async\n\n    waitForAnimationAndContinue('132', function () {\n      render(\n        <div>\n          <My key=\"#4\" {...anim}>\n            4\n          </My>\n          <My key=\"#1\" {...anim}>\n            1\n          </My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('41', function () {\n        render(null, container);\n        done();\n      });\n    });\n  });\n\n  it('should render class component extending AnimatedComponent to a string', () => {\n    const MyComponent = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    const anim = {\n      onComponentDidAppear: componentDidAppear,\n      onComponentWillDisappear: componentWillDisappear,\n    };\n\n    const outputStr = renderToString(<MyComponent {...anim}>1</MyComponent>);\n    expect(outputStr).toBe('<div>1</div>');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-animation/__tests__/animatedComponentTypings.tsx",
    "content": "import { type InfernoNode, render } from 'inferno';\nimport { AnimatedComponent } from 'inferno-animation';\n\ndescribe('inferno-animation AnimatedComponent', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n  });\n\n  it('Should be possible to define typed props for AnimatedComponent', () => {\n    interface MyProps {\n      number: number;\n    }\n\n    class MyComponent extends AnimatedComponent<MyProps, any> {\n      public render(props): InfernoNode {\n        return <div>{props.number}</div>;\n      }\n    }\n\n    render(<MyComponent number={1} />, container);\n\n    expect(container.innerHTML).toBe('<div>1</div>');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-animation/__tests__/animatedMoveComponent.spec.tsx",
    "content": "import { render, type InfernoNode } from 'inferno';\nimport { renderToString } from 'inferno-server';\nimport { AnimatedMoveComponent, componentWillMove } from 'inferno-animation';\n\ndescribe('inferno-animation AnimatedMoveComponent', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  function waitForAnimationAndContinue(condition, callback, arg1?): void {\n    if (container.textContent !== condition) {\n      setTimeout(\n        waitForAnimationAndContinue.bind(null, condition, callback, arg1),\n        10,\n      );\n      return;\n    }\n\n    callback(arg1);\n  }\n\n  function afterEachClear(done): void {\n    container.innerHTML = '';\n    document.body.removeChild(container);\n    done();\n  }\n\n  afterEach(function (done) {\n    render(null, container);\n    waitForAnimationAndContinue('', afterEachClear, done);\n  });\n\n  it('should render class component extending AnimatedMoveComponent into DOM', () => {\n    class MyComponent extends AnimatedMoveComponent<any, any> {\n      public render({ children }): InfernoNode {\n        return <div>{children}</div>;\n      }\n    }\n\n    render(<MyComponent>1</MyComponent>, container);\n    expect(container.textContent).toBe('1');\n  });\n\n  it('should remove class component extending AnimatedMoveComponent from DOM', (done) => {\n    class My extends AnimatedMoveComponent<any, any> {\n      public render({ children }): InfernoNode {\n        return <div>{children}</div>;\n      }\n    }\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#2\">2</My>\n        <My key=\"#3\">3</My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#3\">3</My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedMoveComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n\n    waitForAnimationAndContinue('13', function () {\n      render(\n        <div>\n          <My key=\"#1\">1</My>\n          <My key=\"#4\">4</My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('14', function () {\n        done();\n      });\n    });\n  });\n\n  it('should move class component extending AnimatedMoveComponent from DOM', (done) => {\n    class My extends AnimatedMoveComponent<any, any> {\n      public render({ children }): InfernoNode {\n        return <div>{children}</div>;\n      }\n    }\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#2\">2</My>\n        <My key=\"#3\">3</My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\">1</My>\n        <My key=\"#3\">3</My>\n        <My key=\"#2\">2</My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedMoveComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n    // Disappear animations complete async\n\n    waitForAnimationAndContinue('132', function () {\n      render(\n        <div>\n          <My key=\"#4\">4</My>\n          <My key=\"#1\">1</My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('41', function () {\n        render(null, container);\n        done();\n      });\n    });\n  });\n\n  it('should render class component extending AnimatedMoveComponent to a string', () => {\n    class MyComponent extends AnimatedMoveComponent<any, any> {\n      public render({ children }): InfernoNode {\n        return <div>{children}</div>;\n      }\n    }\n\n    const outputStr = renderToString(<MyComponent>1</MyComponent>);\n    expect(outputStr).toBe('<div>1</div>');\n  });\n});\n\ndescribe('inferno-animation animated functional component', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  function waitForAnimationAndContinue(condition, callback, arg1?): void {\n    if (container.textContent !== condition) {\n      setTimeout(\n        waitForAnimationAndContinue.bind(null, condition, callback, arg1),\n        10,\n      );\n      return;\n    }\n\n    callback(arg1);\n  }\n\n  function afterEachClear(done): void {\n    container.innerHTML = '';\n    document.body.removeChild(container);\n    done();\n  }\n\n  afterEach(function (done) {\n    render(null, container);\n    waitForAnimationAndContinue('', afterEachClear, done);\n  });\n\n  it('should render class component extending AnimatedMoveComponent into DOM', () => {\n    const MyComponent = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    render(\n      <MyComponent onComponentWillMove={componentWillMove}>1</MyComponent>,\n      container,\n    );\n    expect(container.textContent).toBe('1');\n  });\n\n  it('should remove class component extending AnimatedMoveComponent from DOM', (done) => {\n    const My = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    const anim = {\n      onComponentWillMove: componentWillMove,\n    };\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#2\" {...anim}>\n          2\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedMoveComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n\n    waitForAnimationAndContinue('13', function () {\n      render(\n        <div>\n          <My key=\"#1\" {...anim}>\n            1\n          </My>\n          <My key=\"#4\" {...anim}>\n            4\n          </My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('14', function () {\n        done();\n      });\n    });\n  });\n\n  it('should move class component extending AnimatedMoveComponent from DOM', (done) => {\n    const My = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    const anim = {\n      onComponentWillMove: componentWillMove,\n    };\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#2\" {...anim}>\n          2\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n      </div>,\n      container,\n    );\n    expect(container.textContent).toBe('123');\n\n    render(\n      <div>\n        <My key=\"#1\" {...anim}>\n          1\n        </My>\n        <My key=\"#3\" {...anim}>\n          3\n        </My>\n        <My key=\"#2\" {...anim}>\n          2\n        </My>\n      </div>,\n      container,\n    );\n\n    /**\n     * The reason for recursively calling checkRenderComplete_XXX instead of\n     * using a simpler setTimeout is due to a couple of async calls during the animations\n     * hooks of AnimatedMoveComponent. These can cause a setTimeout in the test to\n     * trigger prior to the animation callbacks and thus remove operations haven't yet\n     * been completed. As long as the render operation eventually completes correctly,\n     * the test should be considered successful.\n     */\n    // Disappear animations complete async\n\n    waitForAnimationAndContinue('132', function () {\n      render(\n        <div>\n          <My key=\"#4\" {...anim}>\n            4\n          </My>\n          <My key=\"#1\" {...anim}>\n            1\n          </My>\n        </div>,\n        container,\n      );\n\n      waitForAnimationAndContinue('41', function () {\n        render(null, container);\n        done();\n      });\n    });\n  });\n\n  it('should render class component extending AnimatedMoveComponent to a string', () => {\n    const MyComponent = ({ children }): InfernoNode => {\n      return <div>{children}</div>;\n    };\n\n    const anim = {\n      onComponentWillMove: componentWillMove,\n    };\n\n    const outputStr = renderToString(<MyComponent {...anim}>1</MyComponent>);\n    expect(outputStr).toBe('<div>1</div>');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-animation/__tests__/index.spec.tsx",
    "content": "import { AnimatedComponent, utils } from 'inferno-animation';\n\ndescribe('inferno-animation public API', () => {\n  it('should expose AnimatedComponent', () => {\n    expect(AnimatedComponent).not.toBeUndefined();\n  });\n  it('should expose utils', () => {\n    const {\n      addClassName,\n      removeClassName,\n      registerTransitionListener,\n      forceReflow,\n      clearDimensions,\n      getDimensions,\n      setDimensions,\n      setDisplay,\n    } = utils;\n    expect(addClassName).not.toBeUndefined();\n    expect(removeClassName).not.toBeUndefined();\n    expect(registerTransitionListener).not.toBeUndefined();\n    expect(forceReflow).not.toBeUndefined();\n    expect(clearDimensions).not.toBeUndefined();\n    expect(getDimensions).not.toBeUndefined();\n    expect(setDimensions).not.toBeUndefined();\n    expect(setDisplay).not.toBeUndefined();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-animation/__tests__/utils.spec.tsx",
    "content": "import {\n  addClassName,\n  clearDimensions,\n  forceReflow,\n  getDimensions,\n  registerTransitionListener,\n  removeClassName,\n  setDimensions,\n  setDisplay,\n} from '../src/utils';\n\ndescribe('inferno-animation utils', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  function renderTemplate(dom): void {\n    dom.innerHTML = '<div><div class=\"target\">content</div></div>';\n  }\n\n  it('addClassName', () => {\n    renderTemplate(container);\n    const el = document.querySelector('.target') as HTMLElement;\n    addClassName(el, 'test');\n    addClassName(el, '');\n    expect(el.className).toEqual('target test');\n  });\n\n  it('removeClassName', () => {\n    renderTemplate(container);\n    const el = document.querySelector('.target') as HTMLElement;\n    removeClassName(el, 'target');\n    removeClassName(el, '');\n    expect(el.className).toEqual('');\n  });\n\n  it('forceReflow', () => {\n    renderTemplate(container);\n    const res = forceReflow();\n    expect(res).not.toBeUndefined();\n  });\n\n  it('setDisplay', () => {\n    renderTemplate(container);\n    const el = document.querySelector('.target') as HTMLElement;\n    setDisplay(el, 'block');\n    setDisplay(el, 'block');\n    expect(el.style.getPropertyValue('display')).toEqual('block');\n\n    // Removes style prop\n    setDisplay(el, undefined);\n    // NOTE: For some reason we get a lingering 'style' attribute in on the DOM\n    // element. This is the recomended though\n    // https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute\n    expect(el.outerHTML).toEqual('<div class=\"target\" style=\"\">content</div>');\n\n    // Just clear display prop\n\n    setDisplay(el, 'block');\n    setDimensions(el, 10, 10);\n    setDisplay(el, undefined);\n    expect(el.style.getPropertyValue('display')).toEqual('');\n  });\n\n  it('getDimensions', () => {\n    renderTemplate(container);\n    const el = document.querySelector('.target') as HTMLElement;\n    const res = getDimensions(el);\n    expect(res).not.toEqual(undefined);\n\n    el.style.display = 'none';\n    const res2 = getDimensions(el);\n    expect(res2).not.toEqual(undefined);\n  });\n\n  it('setDimensions', () => {\n    renderTemplate(container);\n    const el = document.querySelector('.target') as HTMLElement;\n    setDimensions(el, 10, 10);\n    const width = el.style.getPropertyValue('width');\n    const height = el.style.getPropertyValue('height');\n    expect(width).toEqual('10px');\n    expect(height).toEqual('10px');\n  });\n\n  it('clearDimensions', () => {\n    renderTemplate(container);\n    const el = document.querySelector('.target') as HTMLElement;\n    setDimensions(el, 10, 10);\n    clearDimensions(el);\n    const width = el.style.getPropertyValue('width');\n    const height = el.style.getPropertyValue('height');\n    expect(width).toEqual('');\n    expect(height).toEqual('');\n  });\n\n  it('registerTransitionListener', (done) => {\n    renderTemplate(container);\n    const el = document.querySelector('.target') as HTMLElement;\n\n    registerTransitionListener([el], () => {\n      // We should always get a callback\n      done();\n    });\n  });\n\n  it('registerTransitionListener for IMG', (done) => {\n    container.innerHTML = '<div><img class=\"target\" /></div>';\n    const el = document.querySelector('.target') as HTMLElement;\n\n    registerTransitionListener([el], () => {\n      // We should always get a callback\n      done();\n    });\n    el.dispatchEvent(new Event('load'));\n  });\n});\n"
  },
  {
    "path": "packages/inferno-animation/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-animation/index.css",
    "content": ":root {\n  --infernoAnimationEnter: all 0.3s ease-out;\n  --infernoAnimationLeave: all 0.2s ease-out;\n}\n\n.inferno-animation-leave {\n  /* Leave animation start state */\n  opacity: 1;\n}\n\n.inferno-animation-leave-active {\n  /* Leave animation transitions */\n  overflow: hidden;\n  transition: var(--infernoAnimationLeave);\n}\n\n.inferno-animation-leave-end {\n  /* Leave animation end state */\n  opacity: 0;\n  height: 0;\n  padding-top: 0;\n  padding-bottom: 0;\n  margin-top: 0;\n  margin-bottom: 0;\n  border-top-width: 0;\n  border-bottom-width: 0;\n}\n\n.inferno-animation-enter {\n  /* Enter animation start state */\n  opacity: 0;\n  height: 0;\n  padding-top: 0;\n  padding-bottom: 0;\n  margin-top: 0;\n  margin-bottom: 0;\n  border-top-width: 0;\n  border-bottom-width: 0;\n}\n\n.inferno-animation-enter-active {\n  /* Enter animation transitions */\n  transition: var(--infernoAnimationEnter);\n}\n\n.inferno-animation-enter-end {\n  /* Enter animation end state */\n  opacity: 1;\n}\n"
  },
  {
    "path": "packages/inferno-animation/package.json",
    "content": "{\n  \"name\": \"inferno-animation\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Animation helpers inferno. This package can be used to reuse server side rendered html\",\n  \"author\": {\n    \"name\": \"Sebastian Ware\",\n    \"email\": \"sebastian@urbantalk.se\",\n    \"url\": \"https://github.com/jhsware\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-animation\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"files\": [\n    \"index.cjs\",\n    \"index.css\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"keywords\": [\n    \"babel\",\n    \"react\",\n    \"inferno\",\n    \"framework\",\n    \"interfaces\",\n    \"user interfaces\",\n    \"vdom\",\n    \"animation\",\n    \"css\"\n  ],\n  \"dependencies\": {\n    \"inferno\": \"9.0.11\"\n  },\n  \"devDependencies\": {\n    \"inferno-create-element\": \"9.0.11\",\n    \"inferno-shared\": \"9.0.11\",\n    \"inferno-utils\": \"9.0.11\",\n    \"inferno-vnode-flags\": \"9.0.11\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\",\n      \"inferno-vnode-flags\"\n    ],\n    \"moduleName\": \"Inferno.Animation\",\n    \"moduleGlobals\": {\n      \"inferno\": \"Inferno\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno-animation/readme.md",
    "content": "# inferno-animation\n\nHelper components and utils to add smooth CSS-animations to your Inferno apps. Extend from `<AnimatedComponent>` and include the css from index.css in this package to get default animation on opacity and height. Requires setting `box-sizing: border-box;` on the animated element.\n\nIf you want to customise your animations, just use index.css as a template and replace \"inferno-animation\" prefix in the CSS-class names with your custom animation name (i.e. mySuperAnimation). Then pass that name to your animated component as an attribute `<MyComponent animation=\"mySuperAnimation\" />` and your customised animation will be used.\n\nFor examples of what animations look like you can try inferno/docs/animations/index.html.\n\n## Install\n\n```\nnpm install inferno-animation\n```\n\n## Usage\n\nThere are three base components you can extend from to get animations in a straightforward way without any wiring.\n\n- AnimatedComponent -- animates on add/remove\n- AnimatedMoveComponent -- animates on move (within the same parent)\n- AnimatedAllComponent -- animates on add/remove and move (within the same parent)\n\nYou can also animate functional components. There are a couple of examples of animations in the main repos in the `docs/animations` and `docs/animations-demo` folder.\n\nIf you don't want to extend from one of the pre-wired components, look att src/AnimatedAllComponent.ts to see\nhow to wire up the three animation hooks:\n\n- componentDidAppear\n- componentWillDisappear\n- componentWillMove\n\nUsing AnimatedAllComponent is just like working with ordinary components. Don't forget to\nadd the CSS or you can get strange results:\n\napp.js\n\n```js\nimport { Component } from 'inferno';\nimport { AnimatedAllComponent } from 'inferno-animation';\nimport './app.css';\n\n// Animate on add/remove\nclass MyAnimated extends AnimatedAllComponent {\n  render() {\n    return <li className=\"test\">{this.props.children}</li>;\n  }\n}\n\nclass MyList extends Component {\n  constructor() {\n    super();\n    this.state = {\n      items: [1, 2, 3, 4, 5],\n    };\n  }\n\n  render() {\n    return (\n      <ul>\n        {this.state.items.map((item) => (\n          <MyAnimated animation=\"inferno-animation\">{item}</MyAnimated>\n        ))}\n      </ul>\n    );\n  }\n}\n```\n\napp.css\n\n```css\n@import '~inferno-animation/index.css';\nul {\n  list-style: none;\n  padding: 0;\n  margin: 0;\n}\n\nli.test {\n  box-sizing: border-box;\n  font-size: 2em;\n  background: #ddd;\n  border-bottom: 1px solid white;\n}\n```\n\nThe syntax for hooking up a function component is straight forward too:\n\n```js\nimport {\n  componentDidAppear,\n  componentWillDisappear,\n  componentWillMove,\n} from 'inferno-animation';\n\n<MyFuncComponent\n  onComponentDidAppear={componentDidAppear}\n  onComponentWillDisappear={componentWillDisappear}\n  onComponentWillMove={componentWillMove}\n>\n  ...\n</MyFuncComponent>;\n```\n\nIMPORTANT! Always use the provided helper methods instead of implementing the hooks yourself. There\nmight be optimisations and/or changes to how the animation hooks are implemented in future versions\nof Inferno that you want to benefit from.\n\n### Global animations\n\nGlobal animations allow you to animate a component between positions on two different \"pages\". Technincally this means they don't have the same parent element. When you mount one page imediately after unmounting the other page, inferno-animation will perform a FLIP-animation between the two positions. To match the elements you use the attribute `globalAnimationKey` which accept a string.\n\nGlobal animations are very simple to use, [check this example.](https://github.com/infernojs/inferno/blob/master/docs/animations-global-demo/app.js)\n\n### Bootstrap style modal animation\n\nThis is an example of how you could implement a Bootstrap style Modal animation using inferno-animation. These two animations are used both for the backdrop and the modal and the purpose is to support the CSS-rules without modification.\n\n- always use the inferno-animation utility functions\n- implementation is straight forward\n- `callback` in animateModalOnWillDisappear triggers the dom-removal in Inferno and is crucial!\n\nCustom animations won't be coordinated with the standard animations to reduce reflow, but performance is not an issue with just a few animations running simultaneously. Use the standard animations for grid or list items.\n\nCall these helper methods from `componentDidAppear` and `componentWillDisapper` of your backdrop and content component when you build a Bootstrap style modal.\n\n```js\nimport { utils } from 'inferno-animation';\nconst {\n  addClassName,\n  removeClassName,\n  registerTransitionListener,\n  forceReflow,\n  setDisplay,\n} = utils;\n\nexport function animateModalOnWillDisappear(dom, callback, onClosed) {\n  registerTransitionListener([dom], () => {\n    // Always call the dom removal callback first!\n    callback && callback();\n    onClosed && onClosed();\n  });\n\n  setTimeout(() => {\n    removeClassName(dom, 'show');\n  }, 5);\n}\n\nexport function animateModalOnDidAppear(dom, onOpened) {\n  setDisplay(dom, 'none');\n  addClassName(dom, 'fade');\n  forceReflow(dom);\n  setDisplay(dom, undefined);\n\n  registerTransitionListener([dom, dom.children[0]], function () {\n    // *** Cleanup ***\n    setDisplay(dom, undefined);\n    onOpened && onOpened(dom);\n  });\n\n  addClassName(dom, 'show');\n}\n```\n"
  },
  {
    "path": "packages/inferno-animation/src/AnimatedAllComponent.ts",
    "content": "import { Component, type InfernoNode, type ParentDOM } from 'inferno';\nimport {\n  type AnimationClass,\n  componentDidAppear,\n  componentWillDisappear,\n  componentWillMove,\n} from './animations';\n\ninterface AnimationProp {\n  animation?: string | AnimationClass;\n  children?: InfernoNode;\n}\n\nexport abstract class AnimatedAllComponent<P, S> extends Component<\n  AnimationProp & P,\n  S\n> {\n  public componentDidAppear(dom: HTMLElement | SVGElement): void {\n    componentDidAppear(dom, this.props);\n  }\n\n  public componentWillDisappear(\n    dom: HTMLElement | SVGElement,\n    callback: () => void,\n  ): void {\n    componentWillDisappear(dom, this.props, callback);\n  }\n\n  public componentWillMove(\n    parentVNode,\n    parent: ParentDOM,\n    dom: HTMLElement | SVGElement,\n  ): void {\n    componentWillMove(parentVNode, parent, dom, this.props);\n  }\n}\n"
  },
  {
    "path": "packages/inferno-animation/src/AnimatedComponent.ts",
    "content": "import { Component, type InfernoNode } from 'inferno';\nimport {\n  type AnimationClass,\n  componentDidAppear,\n  componentWillDisappear,\n} from './animations';\n\ninterface AnimationProp {\n  animation?: string | AnimationClass;\n  children?: InfernoNode;\n}\n\nexport abstract class AnimatedComponent<P, S> extends Component<\n  AnimationProp & P,\n  S\n> {\n  public componentDidAppear(dom: HTMLElement): void {\n    componentDidAppear(dom, this.props);\n  }\n\n  public componentWillDisappear(\n    dom: HTMLElement | SVGElement,\n    callback: () => void,\n  ): void {\n    componentWillDisappear(dom, this.props, callback);\n  }\n}\n"
  },
  {
    "path": "packages/inferno-animation/src/AnimatedMoveComponent.ts",
    "content": "import { Component, type InfernoNode } from 'inferno';\nimport { type AnimationClass, componentWillMove } from './animations';\n\ninterface AnimationProp {\n  animation?: string | AnimationClass;\n  children?: InfernoNode;\n}\n\nexport abstract class AnimatedMoveComponent<P, S> extends Component<\n  AnimationProp & P,\n  S\n> {\n  public componentWillMove(\n    parentVNode,\n    parent: HTMLElement | SVGElement,\n    dom: HTMLElement | SVGElement,\n  ): void {\n    componentWillMove(parentVNode, parent, dom, this.props);\n  }\n}\n"
  },
  {
    "path": "packages/inferno-animation/src/animationCoordinator.ts",
    "content": "import { forceReflow } from './utils';\n\n// This is only used for development and should be set to false for release\n// eslint-disable-next-line no-constant-binary-expression\nconst _DBG_COORD_ = false && process.env.NODE_ENV !== 'production';\n\nexport const enum AnimationPhase {\n  INITIALIZE,\n  MEASURE,\n  SET_START_STATE,\n  ACTIVATE_TRANSITIONS,\n  REGISTER_LISTENERS,\n  ACTIVATE_ANIMATION,\n  length, // This will equal length of actual phases since TS converts this to a zero based list of ints\n}\n\ntype GlobalAnimationKey = string;\nexport interface GlobalAnimationState {\n  width: number;\n  height: number;\n  x: number;\n  y: number;\n  ticks: number;\n}\nconst _globalAnimationSources: Record<\n  GlobalAnimationKey,\n  GlobalAnimationState\n> = {};\n\nexport function _globalAnimationGC(): void {\n  let entriesLeft = false;\n\n  for (const key in _globalAnimationSources) {\n    if (--_globalAnimationSources[key].ticks < 0) {\n      delete _globalAnimationSources[key];\n    } else entriesLeft = true;\n  }\n\n  if (entriesLeft) {\n    requestAnimationFrame(_globalAnimationGC);\n  }\n}\n\nexport function addGlobalAnimationSource(\n  key: GlobalAnimationKey,\n  state: GlobalAnimationState,\n): void {\n  state.ticks = 5;\n  _globalAnimationSources[key] = state;\n\n  if (_globalAnimationGC === null) {\n    requestAnimationFrame(_globalAnimationGC);\n  }\n}\n\nexport function consumeGlobalAnimationSource(\n  key: GlobalAnimationKey,\n): GlobalAnimationState {\n  const tmp = _globalAnimationSources[key];\n  if (tmp !== undefined) {\n    delete _globalAnimationSources[key];\n  }\n  return tmp;\n}\n\nlet _animationQueue: Array<(phase: AnimationPhase) => void> = [];\nlet _animationActivationQueue: Array<(phase: AnimationPhase) => void> = [];\nconst IDLE = 0;\nlet _nextAnimationFrame: number = IDLE;\nlet _nextActivateAnimationFrame: number = IDLE;\n\nfunction _runActivateAnimationPhase(): void {\n  _nextActivateAnimationFrame = IDLE;\n  // Get animations to execute\n  const animationQueue = _animationActivationQueue;\n  // Clear global queue\n  _animationActivationQueue = [];\n\n  for (let i = 0; i < animationQueue.length; i++) {\n    animationQueue[i](AnimationPhase.ACTIVATE_ANIMATION);\n  }\n}\n\nfunction _runAnimationPhases(): void {\n  _nextAnimationFrame = IDLE;\n\n  // Get animations to execute\n  const animationQueue = _animationQueue;\n  // Clear global queue\n  _animationQueue = [];\n\n  // So what this does is run the animation phases in order. Most of the phases are invoked\n  // by a simple call to all the registered callbacks. However:\n  //\n  // - ACTIVATE_TRANSITIONS require a reflow in order to not\n  // interfere with the previous setting of the animation start class\n  //\n  // - ACTIVATE_ANIMATION needs to be called async so the transitions actually fire,\n  // we choose to use an animation frame.\n  //\n  for (let i = 0; i < AnimationPhase.length; i++) {\n    const phase = i as AnimationPhase;\n    switch (phase) {\n      case AnimationPhase.ACTIVATE_ANIMATION:\n        // Final phase - Activate animations\n        // This is a special case and is executed differently from others\n        _animationActivationQueue =\n          _animationActivationQueue.concat(animationQueue);\n        if (_nextActivateAnimationFrame === IDLE) {\n          // Animations are activated on the next animation frame\n          _nextActivateAnimationFrame = requestAnimationFrame(\n            _runActivateAnimationPhase,\n          );\n        }\n        break;\n      default:\n        if (phase === AnimationPhase.ACTIVATE_TRANSITIONS) {\n          // Force reflow before executing ACTIVATE_TRANSITIONS\n          forceReflow();\n        }\n        for (let j = 0; j < animationQueue.length; j++) {\n          animationQueue[j](phase);\n        }\n    }\n  }\n}\n\nfunction _debugAnimationPhases(\n  phase: AnimationPhase,\n  animationQueue: Array<(phase: AnimationPhase) => void>,\n): AnimationPhase {\n  // When debugging we call _runAnimationPhases once for each phase\n  // so only set to idle when done\n  if (phase === AnimationPhase.length - 1) {\n    _nextAnimationFrame = IDLE;\n  }\n\n  switch (phase) {\n    case AnimationPhase.ACTIVATE_ANIMATION:\n      // Final phase - Activate animations\n      // This is a special case and is executed differently from others\n      _animationActivationQueue =\n        _animationActivationQueue.concat(animationQueue);\n      if (_nextActivateAnimationFrame === IDLE) {\n        // Animations are activated on the next animation frame\n        _nextActivateAnimationFrame = requestAnimationFrame(\n          _runActivateAnimationPhase,\n        );\n      }\n      break;\n    default:\n      if (phase === AnimationPhase.ACTIVATE_TRANSITIONS) {\n        // Force reflow before executing ACTIVATE_TRANSITIONS\n        forceReflow();\n      }\n      for (let j = 0; j < animationQueue.length; j++) {\n        animationQueue[j](phase);\n      }\n  }\n  return phase + 1;\n}\n\nexport function queueAnimation(\n  callback: (phase: AnimationPhase) => void,\n): void {\n  _animationQueue.push(callback);\n  if (_nextAnimationFrame === IDLE) {\n    if (!_DBG_COORD_) {\n      _nextAnimationFrame = requestAnimationFrame(_runAnimationPhases);\n    } else {\n      /** ** DEV DEBUGGING code path ****/\n      // Run animation phases one at a time when debugging\n      // to allow visually inspecting changes.\n      let _animationDebugQueue = _animationQueue;\n      const _runPhase = (startPhase: AnimationPhase): void => {\n        _nextAnimationFrame = requestAnimationFrame(() => {\n          // Reset the global animation queue so any changes\n          // added during this animation round is queued\n          if (_animationDebugQueue === _animationQueue) {\n            _animationQueue = [];\n          }\n\n          const nextStartPhase = _debugAnimationPhases(\n            startPhase,\n            _animationDebugQueue,\n          );\n          if (\n            nextStartPhase !== undefined &&\n            nextStartPhase < AnimationPhase.length\n          ) {\n            _runPhase(nextStartPhase);\n          } else if (_animationQueue.length > 0) {\n            // All phases done, check if the queue has been repopulated\n            // and rerun if it has\n            _animationDebugQueue = _animationQueue;\n            _runPhase(0);\n          }\n        });\n      };\n      // TODO: We could create hooks to show a simply UI to control\n      // animation execution. For now you need to set a break point\n      _runPhase(0);\n      /** ** /end DEV DEBUGGING ****/\n    }\n  }\n}\n\n// This is needed for tests. Coordinated animations are run on\n// next animation frame, so we need to make sure we wait for them to finish.\nexport function hasPendingAnimations(): boolean {\n  return _nextAnimationFrame !== IDLE || _nextActivateAnimationFrame !== IDLE;\n}\n"
  },
  {
    "path": "packages/inferno-animation/src/animations.ts",
    "content": "import {\n  addClassName,\n  clearDimensions,\n  clearTransform,\n  decrementMoveCbCount,\n  forceReflow,\n  getDimensions,\n  getGeometry,\n  incrementMoveCbCount,\n  registerTransitionListener,\n  removeClassName,\n  resetDisplay,\n  setDimensions,\n  setDisplay,\n  setTransform,\n} from './utils';\nimport {\n  addGlobalAnimationSource,\n  AnimationPhase,\n  consumeGlobalAnimationSource,\n  type GlobalAnimationState,\n  queueAnimation,\n} from './animationCoordinator';\nimport { isNull, isNullOrUndef } from 'inferno-shared';\nimport { type ParentDOM } from 'inferno';\n\nexport interface AnimationClass {\n  active: string;\n  end: string;\n  start: string;\n}\n\nfunction getAnimationClass(\n  animationProp: AnimationClass | string | undefined | null,\n  prefix: string,\n): AnimationClass {\n  let animCls: AnimationClass;\n\n  if (!isNullOrUndef(animationProp) && typeof animationProp === 'object') {\n    animCls = animationProp;\n  } else {\n    const animationName = animationProp || 'inferno-animation';\n    const placeholder = animationName + prefix;\n    animCls = {\n      active: placeholder + '-active',\n      end: placeholder + '-end',\n      start: placeholder,\n    };\n  }\n\n  return animCls;\n}\n\nexport function componentDidAppear(dom: HTMLElement | SVGElement, props): void {\n  // Get dimensions and unpack class names\n  const cls = getAnimationClass(props.animation, '-enter');\n\n  // Moved measuring to pre_initialize. It causes a reflow for each component beacuse of the setDisplay of previous component.\n  const dimensions = {};\n  const display = setDisplay(dom, 'none');\n  const sourceState =\n    props.globalAnimationKey === undefined\n      ? null\n      : consumeGlobalAnimationSource(props.globalAnimationKey);\n  queueAnimation((phase: AnimationPhase) => {\n    _didAppear(phase, dom, cls, dimensions, display, sourceState);\n  });\n}\n\nfunction _getDidAppearTransitionCallback(dom, cls) {\n  return () => {\n    // 5. Remove the element\n    clearDimensions(dom);\n    removeClassName(dom, cls.active + ' ' + cls.end);\n    // 6. Call callback to allow stuff to happen\n    // Not currently used but this is where one could\n    // add a call to something like this.didAppearDone\n  };\n}\n\nfunction _didAppear(\n  phase: AnimationPhase,\n  dom: HTMLElement | SVGElement,\n  cls: AnimationClass,\n  dimensions,\n  display: string,\n  sourceState: GlobalAnimationState | null,\n): void {\n  switch (phase) {\n    case AnimationPhase.INITIALIZE:\n      // Needs to be done in a single pass to avoid reflows\n      // We set display: none whilst waiting for an animation frame to avoid flicker\n      resetDisplay(dom, display);\n      return;\n    case AnimationPhase.MEASURE:\n      // In case of img element that hasn't been loaded, just trigger reflow\n      if (dom.tagName !== 'IMG' || (dom as any).complete) {\n        const tmp = getDimensions(dom);\n        dimensions.x = tmp.x;\n        dimensions.y = tmp.y;\n        dimensions.width = tmp.width;\n        dimensions.height = tmp.height;\n      } else {\n        forceReflow();\n      }\n      return;\n    case AnimationPhase.SET_START_STATE:\n      // 1. Set start of animation\n      if (\n        !isNullOrUndef(sourceState) &&\n        dimensions.width !== 0 &&\n        dimensions.height !== 0\n      ) {\n        // const diffX = (sourceState.width - dimensions.width) / 2;\n        // const diffY = (sourceState.height - dimensions.height) / 2;\n        const dx = sourceState.x - dimensions.x;\n        const dy = sourceState.y - dimensions.y;\n        const scaleX = sourceState.width / dimensions.width;\n        const scaleY = sourceState.height / dimensions.height;\n        setTransform(dom, dx, dy, scaleX, scaleY);\n      }\n      addClassName(dom, cls.start);\n      return;\n    case AnimationPhase.ACTIVATE_TRANSITIONS:\n      // 2. Activate transition (after a reflow)\n      addClassName(dom, cls.active);\n      return;\n    case AnimationPhase.REGISTER_LISTENERS:\n      // 3. Set an animation listener, code at end\n      // Needs to be done after activating so timeout is calculated correctly\n      registerTransitionListener(\n        // *** Cleanup is broken out as micro optimisation ***\n        [dom],\n        _getDidAppearTransitionCallback(dom, cls),\n      );\n      return;\n    case AnimationPhase.ACTIVATE_ANIMATION:\n      // 4. Activate target state (called async via requestAnimationFrame)\n      if (\n        !isNullOrUndef(sourceState) &&\n        dimensions.width !== 0 &&\n        dimensions.height !== 0\n      ) {\n        clearTransform(dom);\n      }\n      setDimensions(dom, dimensions.width, dimensions.height);\n      removeClassName(dom, cls.start);\n      addClassName(dom, cls.end);\n  }\n}\n\nexport function componentWillDisappear(\n  dom: HTMLElement | SVGElement,\n  props,\n  callback: () => void,\n): void {\n  // Get dimensions and unpack class names\n  const cls = getAnimationClass(props.animation, '-leave');\n  const dimensions = getDimensions(dom);\n  queueAnimation((phase) => {\n    _willDisappear(phase, dom, callback, cls, dimensions);\n  });\n  if (props.globalAnimationKey !== undefined) {\n    addGlobalAnimationSource(\n      props.globalAnimationKey,\n      dimensions as GlobalAnimationState,\n    );\n    dom.style.setProperty('visibility', 'hidden');\n  }\n}\n\nfunction _willDisappear(\n  phase: AnimationPhase,\n  dom: HTMLElement | SVGElement,\n  callback: () => void,\n  cls: AnimationClass,\n  dimensions,\n): void {\n  switch (phase) {\n    case AnimationPhase.MEASURE:\n      // 1. Set animation start state and dimensions\n      setDimensions(dom, dimensions.width, dimensions.height);\n      addClassName(dom, cls.start);\n      return;\n    case AnimationPhase.ACTIVATE_TRANSITIONS:\n      // 2. Activate transition (after a reflow)\n      addClassName(dom, cls.active);\n      return;\n    case AnimationPhase.REGISTER_LISTENERS:\n      // 3. Set an animation listener, code at end\n      // Needs to be done after activating so timeout is calculated correctly\n      registerTransitionListener(\n        // Unlike _didAppear, no cleanup needed since node is removed.\n        // Just passing the componentWillDisappear callback so Inferno can\n        // remove the nodes.\n        [dom],\n        callback,\n      );\n      return;\n    case AnimationPhase.ACTIVATE_ANIMATION:\n      // 4. Activate target state (called async via requestAnimationFrame)\n      addClassName(dom, cls.end);\n      removeClassName(dom, cls.start);\n      clearDimensions(dom);\n  }\n}\n\nexport function componentWillMove(\n  parentVNode,\n  parent: ParentDOM,\n  _dom: HTMLElement | SVGElement,\n  props: any,\n): void {\n  // Measure all siblings of moved node once before any mutations are done\n  let els;\n  if (!parentVNode.$MV) {\n    parentVNode.$MV = true;\n    els = [];\n    // @ts-expect-error parent is not supposed to be null\n    let tmpEl = parent.firstChild as HTMLElement | SVGElement;\n    while (!isNull(tmpEl)) {\n      els.push({\n        dx: 0,\n        dy: 0,\n        geometry: getGeometry(tmpEl),\n        moved: false,\n        node: tmpEl,\n      });\n      tmpEl = tmpEl.nextSibling as HTMLElement | SVGElement;\n    }\n  }\n\n  // Get animation class names\n  const cls = getAnimationClass(props.animation, '-move');\n\n  const animState = {\n    els,\n    isMaster: !isNullOrUndef(els),\n    parentVNode,\n  };\n  queueAnimation((phase) => {\n    _willMove(phase, cls, animState);\n  });\n}\n\nfunction _willMove(\n  phase: AnimationPhase,\n  cls: AnimationClass,\n  animState,\n): void {\n  const { els, isMaster, parentVNode } = animState;\n\n  switch (phase) {\n    case AnimationPhase.MEASURE:\n      // If we are responsible for triggering measures, we check all the target positions\n      if (isMaster) {\n        for (let i = 0; i < els.length; i++) {\n          const tmpItem = els[i];\n          // Make sure we can measure target properly\n          removeClassName(tmpItem.node, cls.active);\n          // Measure\n          const geometry = getGeometry(tmpItem.node);\n          const deltaX = tmpItem.geometry.x - geometry.x;\n          const deltaY = tmpItem.geometry.y - geometry.y;\n          if (deltaX !== 0 || deltaY !== 0) {\n            tmpItem.moved = true;\n            tmpItem.dx = deltaX;\n            tmpItem.dy = deltaY;\n          }\n          // TODO: Check dimensions\n        }\n      }\n      return;\n    case AnimationPhase.SET_START_STATE:\n      /**\n       * At this state we have measure the size of the moving node\n       * both at source and target so now we let the source placeholder\n       * fill the source space and move the node to start position\n       * by transform\n       */\n      if (isMaster) {\n        for (let i = 0; i < els.length; i++) {\n          const tmpItem = els[i];\n          if (tmpItem.moved) {\n            setTransform(tmpItem.node, tmpItem.dx, tmpItem.dy, 1, 1);\n          }\n          // TODO: Set dimensions\n        }\n      }\n      return;\n    case AnimationPhase.ACTIVATE_TRANSITIONS:\n      // A reflow is triggered prior to this step\n      if (isMaster) {\n        for (let i = 0; i < els.length; i++) {\n          const tmpItem = els[i];\n          if (tmpItem.moved) {\n            addClassName(tmpItem.node, cls.active);\n          }\n        }\n      }\n      return;\n    case AnimationPhase.REGISTER_LISTENERS:\n      if (isMaster) {\n        for (let i = 0; i < els.length; i++) {\n          const tmpItem = els[i];\n          if (tmpItem.moved) {\n            registerTransitionListener(\n              // How to know if this is a compound move?\n              [tmpItem.node],\n              _getWillMoveTransitionCallback(tmpItem.node, cls),\n            );\n            // Keep track of how many callbacks will be fired\n            incrementMoveCbCount(tmpItem.node);\n          }\n        }\n      }\n      return;\n    case AnimationPhase.ACTIVATE_ANIMATION:\n      // 10. Apply target geometry of node to target\n      if (isMaster) {\n        for (let i = 0; i < els.length; i++) {\n          const tmpItem = els[i];\n          if (tmpItem.moved) {\n            setTransform(tmpItem.node, 0, 0, 1, 1);\n          }\n        }\n      }\n      // TODO: Set dimensions\n      if (parentVNode.$MV) parentVNode.$MV = false;\n  }\n}\n\nfunction _getWillMoveTransitionCallback(\n  dom: HTMLElement | SVGElement,\n  cls: AnimationClass,\n) {\n  return () => {\n    // Only remove these if the translate has completed\n    const cbCount = decrementMoveCbCount(dom);\n    if (cbCount === 0) {\n      clearDimensions(dom);\n      clearTransform(dom);\n      removeClassName(dom, cls.active);\n    }\n  };\n}\n"
  },
  {
    "path": "packages/inferno-animation/src/index.ts",
    "content": "import {\n  addClassName,\n  clearDimensions,\n  forceReflow,\n  getDimensions,\n  registerTransitionListener,\n  removeClassName,\n  setDimensions,\n  setDisplay,\n} from './utils';\n\nexport { AnimatedAllComponent } from './AnimatedAllComponent';\nexport { AnimatedComponent } from './AnimatedComponent';\nexport { AnimatedMoveComponent } from './AnimatedMoveComponent';\nexport {\n  componentDidAppear,\n  componentWillDisappear,\n  componentWillMove,\n  type AnimationClass,\n} from './animations';\nexport { hasPendingAnimations } from './animationCoordinator';\n\nexport const utils = {\n  addClassName,\n  clearDimensions,\n  forceReflow,\n  getDimensions,\n  registerTransitionListener,\n  removeClassName,\n  setDimensions,\n  setDisplay,\n};\n"
  },
  {
    "path": "packages/inferno-animation/src/utils.ts",
    "content": "import { isFunction } from 'inferno-shared';\n\nexport interface Dimensions {\n  height: number;\n  width: number;\n  x: number;\n  y: number;\n}\n\nfunction filterEmpty(c: string): boolean {\n  return c !== '';\n}\n\nfunction getClassNameList(className: string): string[] {\n  return className.split(' ').filter(filterEmpty);\n}\n\nexport function addClassName(\n  node: HTMLElement | SVGElement,\n  className: string,\n): void {\n  const classNameList = getClassNameList(className);\n\n  for (let i = 0; i < classNameList.length; i++) {\n    node.classList.add(classNameList[i]);\n  }\n}\n\nexport function removeClassName(\n  node: HTMLElement | SVGElement,\n  className: string,\n): void {\n  const classNameList = getClassNameList(className);\n\n  for (let i = 0; i < classNameList.length; i++) {\n    node.classList.remove(classNameList[i]);\n  }\n}\n\nexport function forceReflow(): number {\n  return document.body.clientHeight;\n}\n\n// A quicker version used in pre_initialize\nexport function resetDisplay(\n  node: HTMLElement | SVGElement,\n  value?: string,\n): void {\n  if (value !== undefined) {\n    node.style.setProperty('display', value);\n  } else {\n    node.style.removeProperty('display');\n    _cleanStyle(node);\n  }\n}\n\nexport function setDisplay(\n  node: HTMLElement | SVGElement,\n  value?: string,\n): string {\n  const oldVal = node.style.getPropertyValue('display');\n\n  if (oldVal !== value) {\n    if (value !== undefined) {\n      node.style.setProperty('display', value);\n    } else {\n      node.style.removeProperty('display');\n      _cleanStyle(node);\n    }\n  }\n  return oldVal;\n}\n\nfunction _cleanStyle(node: HTMLElement | SVGElement): void {\n  if (!node.style) {\n    // https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute\n    node.removeAttribute('style');\n  }\n}\n\nexport function getDimensions(node: HTMLElement | SVGElement): Dimensions {\n  const tmpDisplay = node.style.getPropertyValue('display');\n\n  // The `display: none;` workaround was added to support Bootstrap animations in\n  // https://github.com/jhsware/inferno-bootstrap/blob/be4a17bff5e785b993a66a2927846cd463fecae3/src/Modal/AnimateModal.js\n  // we should consider deprecating this, or providing a different solution for\n  // those who only do normal animations.\n  const isDisplayNone =\n    window.getComputedStyle(node).getPropertyValue('display') === 'none';\n  if (isDisplayNone) {\n    node.style.setProperty('display', 'block');\n  }\n\n  const tmp = node.getBoundingClientRect();\n\n  if (isDisplayNone) {\n    // node.style.display = tmpDisplay\n    node.style.setProperty('display', tmpDisplay);\n    _cleanStyle(node);\n  }\n\n  return {\n    height: tmp.height,\n    width: tmp.width,\n    x: tmp.x,\n    y: tmp.y,\n  };\n}\n\nexport function getGeometry(node: HTMLElement | SVGElement): DOMRect {\n  return node.getBoundingClientRect();\n}\n\nexport function setTransform(\n  node: HTMLElement | SVGElement,\n  x: number,\n  y: number,\n  scaleX: number = 1,\n  scaleY: number = 1,\n): void {\n  const doScale = scaleX !== 1 || scaleY !== 1;\n  if (doScale) {\n    node.style.transformOrigin = '0 0';\n    node.style.transform = `translate(${x}px,${y}px) scale(${scaleX},${scaleY})`;\n  } else {\n    node.style.transform = `translate(${x}px,${y}px)`;\n  }\n}\n\nexport function clearTransform(node: HTMLElement | SVGElement): void {\n  node.style.transform = '';\n  node.style.transformOrigin = '';\n}\n\nexport function setDimensions(\n  node: HTMLElement | SVGElement,\n  width: number,\n  height: number,\n): void {\n  node.style.width = width + 'px';\n  node.style.height = height + 'px';\n}\n\nexport function clearDimensions(node: HTMLElement | SVGElement): void {\n  node.style.width = node.style.height = '';\n}\n\nfunction _getMaxTransitionDuration(nodes): {\n  maxDuration: number;\n  nrofTransitions: number;\n} {\n  let nrofTransitions = 0;\n  let maxDuration = 0;\n  for (let i = 0; i < nodes.length; i++) {\n    const node = nodes[i];\n    if (!node) continue;\n\n    const cs = window.getComputedStyle(node);\n    const dur = cs.getPropertyValue('transition-duration').split(',');\n    const del = cs.getPropertyValue('transition-delay').split(',');\n    const props = cs.getPropertyValue('transition-property').split(',');\n\n    for (const prop of props) {\n      const fixedProp = prop.trim();\n      if (fixedProp[0] === '-') {\n        const tmp = fixedProp.split('-').splice(2).join('-');\n        // Since I increase number of transition events to expect by\n        // number of durations found I need to remove browser prefix\n        // variations of the same property\n        if (fixedProp.includes(tmp)) {\n          nrofTransitions--;\n        }\n      }\n    }\n\n    let animTimeout = 0;\n    for (let j = 0; j < dur.length; j++) {\n      const duration = dur[j];\n      const delay = del[j];\n\n      const tp = parseFloat(duration) + parseFloat(delay);\n      if (tp > animTimeout) animTimeout = tp;\n    }\n\n    nrofTransitions += dur.length;\n    // Max duration should be equal to the longest animation duration\n    // of all found transitions including delay\n    if (animTimeout > maxDuration) {\n      maxDuration = animTimeout;\n    }\n  }\n\n  return {\n    maxDuration,\n    nrofTransitions,\n  };\n}\n\nfunction setAnimationTimeout(onTransitionEnd, rootNode, maxDuration): void {\n  if (rootNode.nodeName === 'IMG' && !rootNode.complete) {\n    // Image animations should wait for loaded until the timeout is started, otherwise animation will be cut short\n    // due to loading delay\n    rootNode.addEventListener('load', () => {\n      setTimeout(\n        () => onTransitionEnd({ target: rootNode, timeout: true }),\n        maxDuration === 0 ? 0 : Math.round(maxDuration * 1000) + 100,\n      );\n    });\n  } else {\n    setTimeout(\n      () => onTransitionEnd({ target: rootNode, timeout: true }),\n      maxDuration === 0 ? 0 : Math.round(maxDuration * 1000) + 100,\n    );\n  }\n}\n\n/**\n * You need to pass the root element and ALL animated children that have transitions,\n * if there are any,  so the timeout is set to the longest duration. Otherwise there\n * will be animations that fail to complete before the timeout is triggered.\n *\n * @param nodes a list of nodes that have transitions that are part of this animation\n * @param callback callback when all transitions of participating nodes are completed\n */\nexport function registerTransitionListener(\n  nodes: Array<HTMLElement | SVGElement>,\n  callback: () => void,\n): void {\n  const rootNode = nodes[0];\n\n  /**\n   * Here comes the transition event listener\n   */\n  const transitionDuration = _getMaxTransitionDuration(nodes);\n  const maxDuration = transitionDuration.maxDuration;\n  let nrofTransitionsLeft = transitionDuration.nrofTransitions;\n  let done = false;\n\n  const onTransitionEnd = (event): void => {\n    // Make sure this is an actual event\n    if (!event || done) {\n      return;\n    }\n\n    if (!event.timeout) {\n      // Make sure it isn't a child that is triggering the event\n      let goAhead = false;\n      for (let i = 0; i < nodes.length; i++) {\n        // Note: Check for undefined nodes (happens when an animated el doesn't have children)\n        if (nodes[i] !== undefined && event.target === nodes[i]) {\n          goAhead = true;\n          break;\n        }\n      }\n      if (!goAhead) return;\n\n      // Wait for all transitions\n      if (--nrofTransitionsLeft > 0) {\n        return;\n      }\n    }\n\n    // This is it...\n    done = true;\n\n    /**\n     * Perform cleanup\n     */\n    rootNode.removeEventListener('transitioncancel', onTransitionEnd, false);\n    rootNode.removeEventListener('transitionend', onTransitionEnd, false);\n    if (isFunction(callback)) {\n      callback();\n    }\n  };\n\n  // if element gets removed from the DOM before transition is triggered, browser will raise transitioncancel event\n  rootNode.addEventListener('transitioncancel', onTransitionEnd, false);\n  rootNode.addEventListener('transitionend', onTransitionEnd, false);\n\n  setAnimationTimeout(onTransitionEnd, rootNode, maxDuration);\n}\n\nexport function incrementMoveCbCount(node): number {\n  let curr = parseInt(node.dataset.moveCbCount, 10);\n  if (isNaN(curr)) {\n    curr = 1;\n  } else {\n    curr++;\n  }\n  node.dataset.moveCbCount = curr;\n  return curr;\n}\n\nexport function decrementMoveCbCount(node): number {\n  let curr = parseInt(node.dataset.moveCbCount, 10);\n  if (isNaN(curr)) {\n    curr = 0;\n  } else {\n    curr--;\n    if (curr === 0) {\n      node.dataset.moveCbCount = '';\n    } else {\n      node.dataset.moveCbCount = curr;\n    }\n  }\n  return curr;\n}\n"
  },
  {
    "path": "packages/inferno-clone-vnode/README.md",
    "content": "# Inferno-clone-vnode\n\nThis package can be used to clone Inferno virtual nodes. This package can also be aliased to `React.cloneElement`.\n\n```\nimport { cloneVNode } from 'inferno-clone-vnode';\n\nconst cloned = cloneVNode(\n  vNode,\n  [props],\n  [...children]\n)\n```\n\nClone and return a new Inferno vNode using element as the starting point.\nThe resulting element will have the original element’s props with the new props merged in shallowly.\nNew children will replace existing children. key and ref from the original element will be preserved.\n"
  },
  {
    "path": "packages/inferno-clone-vnode/__tests__/cloneVNode.spec.tsx",
    "content": "import { cloneVNode } from 'inferno-clone-vnode';\nimport {\n  Component,\n  createTextVNode,\n  Fragment,\n  InfernoNode,\n  type InfernoSingleNode,\n  render,\n  type VNode,\n} from 'inferno';\n\ndescribe('cloneVNode (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n  });\n\n  it('should clone a tag', () => {\n    const node = cloneVNode(<a />, null);\n    render(node, container);\n    expect(container.innerHTML).toBe('<a></a>');\n  });\n\n  it('should clone with third argument array', () => {\n    const node = cloneVNode(<div />, null, [<span />]);\n    render(node, container);\n    expect(container.innerHTML).toBe('<div><span></span></div>');\n  });\n\n  it('should clone with third argument overriding props and cloned node children', () => {\n    const node = cloneVNode(<div>f</div>, { children: 'x' }, [<a>1</a>]);\n    render(node, container);\n    expect(container.innerHTML).toBe('<div><a>1</a></div>');\n  });\n\n  it('should clone with third argument overriding props and cloned node children', () => {\n    const node = cloneVNode(<div>f</div>, { children: 'x' }, [undefined]);\n    render(node, container);\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  it('should clone OPT_ELEMENT', () => {\n    const noop = () => {};\n    // noinspection HtmlUnknownAttribute\n    const node = cloneVNode(\n        // @ts-expect-error\n        // eslint-disable-next-line inferno/no-unknown-property\n      <div onComponentWillMount={noop} onComponentDidMount={noop} onComponentWillUnmount={noop} onComponentShouldUpdate={noop} onComponentWillUpdate={noop} />,\n      { children: [<span />] }\n    );\n    render(node, container);\n    expect(container.innerHTML).toBe('<div><span></span></div>');\n  });\n\n  it('should clone a basic element with array children', () => {\n    const node = cloneVNode(<div />, { children: [<span />] });\n    render(node, container);\n    expect(container.innerHTML).toBe('<div><span></span></div>');\n  });\n\n  it('should clone a basic element with children in props and as third argument', () => {\n    const node1 = cloneVNode(\n      <div />,\n      { children: <span>arr1a</span> },\n      <span>arr2b</span>,\n    );\n    render(node1, container);\n    expect(container.innerHTML).toBe('<div><span>arr2b</span></div>');\n\n    const node2 = cloneVNode(\n      <div />,\n      { children: [<span>arr2a</span>] },\n      <span>arr2b</span>,\n    );\n    render(node2, container);\n    expect(container.innerHTML).toBe('<div><span>arr2b</span></div>');\n\n    const node3 = cloneVNode(<div />, { children: [<span>arr3a</span>] }, [\n      <span>arr3b</span>,\n    ]);\n    render(node3, container);\n    expect(container.innerHTML).toBe('<div><span>arr3b</span></div>');\n  });\n\n  it('Should support multiple parameters as children', () => {\n    // @ts-ignore\n    const node = cloneVNode(\n      <div />,\n      null,\n      <span>arr3a</span>,\n      <span>arr3b</span>,\n      <span>arr3c</span>,\n    );\n    render(node, container);\n    expect(container.innerHTML).toBe(\n      '<div><span>arr3a</span><span>arr3b</span><span>arr3c</span></div>',\n    );\n  });\n\n  it('Should support multiple nodes as children inside array', () => {\n    const node = cloneVNode(<div />, null, [\n      <span>arr3a</span>,\n      <span>arr3b</span>,\n      <span>arr3c</span>,\n    ]);\n    render(node, container);\n    expect(container.innerHTML).toBe(\n      '<div><span>arr3a</span><span>arr3b</span><span>arr3c</span></div>',\n    );\n  });\n\n  it('Should support single node as children', () => {\n    const node = cloneVNode(<div />, null, <span>arr3a</span>);\n    render(node, container);\n    expect(container.innerHTML).toBe('<div><span>arr3a</span></div>');\n  });\n\n  it('Should support single node as children inside array', () => {\n    const node = cloneVNode(<div />, null, [<span>arr3a</span>]);\n    render(node, container);\n    expect(container.innerHTML).toBe('<div><span>arr3a</span></div>');\n  });\n\n  it('should clone a basic element with null children', () => {\n    const node = cloneVNode(<div />, { children: null });\n    render(node, container);\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  it('should clone a basic element with key and ref', () => {\n    const ref = () => {};\n    const node = cloneVNode(<div />, { key: 'foo', ref });\n\n    expect(node.key).toBe('foo');\n    expect(node.ref).toBe(ref);\n  });\n\n  it('should clone a basic element with different children and props', () => {\n    const node1 = <div>Hello world</div>;\n    render(node1, container);\n    expect(container.innerHTML).toBe('<div>Hello world</div>');\n\n    const node2 = cloneVNode(node1, null, 'Hello world 2!');\n    render(node2, container);\n    expect(container.innerHTML).toBe('<div>Hello world 2!</div>');\n\n    const node3 = cloneVNode(node2, { className: 'foo' }, 'Hello world 2!');\n    render(node3, container);\n    expect(container.innerHTML).toBe('<div class=\"foo\">Hello world 2!</div>');\n\n    const node4 = cloneVNode(node1, { className: 'foo' }, 'Hello world 3!');\n    render(node4, container);\n    expect(container.innerHTML).toBe('<div class=\"foo\">Hello world 3!</div>');\n  });\n\n  function StatelessComponent(props) {\n    return <div {...props} />;\n  }\n\n  it('should clone a basic stateless component with different children and props', () => {\n    const node1 = <StatelessComponent children=\"Hello world\" />;\n\n    render(node1, container);\n    expect(container.innerHTML).toBe('<div>Hello world</div>');\n    const node2 = cloneVNode(node1, { children: 'Hello world 2!' });\n\n    render(node2, container);\n    expect(container.innerHTML).toBe('<div>Hello world 2!</div>');\n    const node3 = cloneVNode(node1, {\n      children: 'Hello world 3!',\n      className: 'yo',\n    });\n\n    render(node3, container);\n    expect(container.innerHTML).toBe('<div class=\"yo\">Hello world 3!</div>');\n  });\n\n  it('Should prefer falsy children (undefined) if its provided over existing children', () => {\n    const node1 = <div>1</div>;\n    const clone = cloneVNode(node1, null, [undefined]);\n\n    render(clone, container);\n\n    expect(container.innerHTML).toEqual('<div></div>');\n  });\n\n  it('Should clone Component with vNode div children', () => {\n    class Com extends Component<{ children?: InfernoNode }> {\n      public render({ children }) {\n        return children;\n      }\n    }\n    const com1 = (\n      <Com>\n        <div>abc</div>\n      </Com>\n    );\n    const clone = cloneVNode(com1);\n\n    render(clone, container);\n\n    expect(container.innerHTML).toEqual('<div>abc</div>');\n  });\n\n  it('Should clone Component with no props at all', () => {\n    class Com extends Component<{ children?: InfernoNode }> {\n      public render({ children }) {\n        return children;\n      }\n    }\n    const com1 = <Com />;\n    const clone = cloneVNode(com1);\n\n    render(clone, container);\n\n    expect(container.innerHTML).toEqual('');\n  });\n\n  it('Should clone vNode with no props at all', () => {\n    const span = <span />;\n    const clone = cloneVNode(span);\n\n    render(clone, container);\n\n    expect(container.innerHTML).toEqual('<span></span>');\n  });\n\n  it('Should clone Component with vNode text children', () => {\n    class Com extends Component {\n      public render() {\n        return 'Text';\n      }\n    }\n    const com1 = (\n      <Com>\n        <div>1</div>\n      </Com>\n    );\n    const clone = cloneVNode(com1);\n\n    render(clone, container);\n\n    expect(container.innerHTML).toEqual('Text');\n  });\n\n  it('Should clone textVNode', () => {\n    const textNode = createTextVNode('foobar');\n    const clone = cloneVNode(textNode);\n\n    render(clone, container);\n\n    expect(container.innerHTML).toEqual('foobar');\n  });\n\n  it('Should clone textVnode with new content', () => {\n    const textNode = createTextVNode('foobar');\n    const clone = cloneVNode(textNode, null, 'foo');\n\n    render(clone, container);\n\n    expect(container.innerHTML).toEqual('foo');\n  });\n\n  it('Should prefer children in order', () => {\n    function Bar({ children }) {\n      return <div>{children}</div>;\n    }\n\n    const nodeToClone = <Bar>First</Bar>;\n\n    render(nodeToClone, container);\n\n    expect(container.innerHTML).toBe('<div>First</div>');\n\n    render(cloneVNode(nodeToClone, { children: 'Second' }), container);\n\n    expect(container.innerHTML).toBe('<div>Second</div>');\n\n    render(cloneVNode(nodeToClone, { children: 'Second' }, 'Third'), container);\n\n    expect(container.innerHTML).toBe('<div>Third</div>');\n\n    // @ts-ignore\n    render(\n      cloneVNode(nodeToClone, { children: 'Second' }, 'Third', 'Fourth'),\n      container,\n    );\n\n    expect(container.innerHTML).toBe('<div>ThirdFourth</div>');\n  });\n\n  it('Should prefer children in order #2', () => {\n    function Bar({ children }) {\n      return <div>{children}</div>;\n    }\n\n    const nodeToClone = <Bar>First</Bar>;\n\n    render(nodeToClone, container);\n\n    expect(container.innerHTML).toBe('<div>First</div>');\n\n    render(cloneVNode(nodeToClone, null), container);\n\n    expect(container.innerHTML).toBe('<div>First</div>');\n\n    render(cloneVNode(nodeToClone, null, null), container);\n\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  describe('Cloning className', () => {\n    it('Should prefer new props over cloned object', () => {\n      const node = <div className=\"test\" />;\n\n      render(node, container);\n\n      expect(container.firstChild.className).toEqual('test');\n\n      const newNode = cloneVNode(node, {\n        className: 'foo',\n      });\n\n      render(newNode, container);\n      // expect(newNode.props.className).toBe(undefined); , This depends on if we are running inferno-compat or not\n      // expect(newNode.props.hasOwnProperty('className')).toBe(false);\n\n      expect(container.firstChild.className).toBe('foo');\n      expect(container.innerHTML).toEqual('<div class=\"foo\"></div>');\n    });\n\n    it('Should remove className if new one is empty', () => {\n      const node = <div className=\"test\" />;\n\n      render(node, container);\n\n      expect(container.firstChild.className).toEqual('test');\n\n      const newNode = cloneVNode(node, {\n        className: null,\n      });\n\n      render(newNode, container);\n\n      expect(container.firstChild.className).toBe('');\n      expect(container.innerHTML).toEqual('<div></div>');\n    });\n\n    it('Should keep previous className when new props dont have that property at all', () => {\n      const node = <div className=\"test\" />;\n\n      render(node, container);\n\n      expect(container.firstChild.className).toEqual('test');\n\n      const newNode = cloneVNode(node, {\n        id: 'wow',\n      });\n\n      render(newNode, container);\n\n      expect(Object.prototype.hasOwnProperty.call(newNode.props, 'id')).toBe(\n        true,\n      );\n      // expect(newNode.props.className).toBe(undefined);\n      // expect(newNode.props.hasOwnProperty('className')).toBe(false);\n\n      expect(container.firstChild.className).toBe('test');\n      expect(container.firstChild.getAttribute('id')).toBe('wow');\n      expect(container.innerHTML).toEqual('<div class=\"test\" id=\"wow\"></div>');\n    });\n\n    it('Should be possible to add props to children', () => {\n      function Foobar(props) {\n        return <div>{cloneVNode(props.children, { foo: 'bar' })}</div>;\n      }\n\n      function ChildCom(props) {\n        return <div>{props.foo}</div>;\n      }\n\n      render(\n        <Foobar>\n          <ChildCom foo=\"init\" />\n        </Foobar>,\n        container,\n      );\n\n      expect(container.innerHTML).toEqual('<div><div>bar</div></div>');\n    });\n  });\n\n  describe('Cloning key', () => {\n    it('Should prefer new props over cloned object', () => {\n      const node = <div key=\"test\" />;\n\n      expect(node.key).toEqual('test');\n\n      render(node, container);\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      const newNode = cloneVNode(node, {\n        key: 'foo',\n      });\n\n      expect(newNode.key).toEqual('foo');\n      expect(newNode.props.ref).toBe(undefined);\n      // expect(newNode.props.hasOwnProperty('key')).toBe(false);\n      render(newNode, container);\n      expect(container.innerHTML).toEqual('<div></div>');\n    });\n\n    it('Should remove key if new one is empty', () => {\n      const node = <div key=\"test\" />;\n\n      expect(node.key).toEqual('test');\n\n      render(node, container);\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      const newNode = cloneVNode(node, {\n        key: null,\n      });\n\n      expect(newNode.key).toEqual(null);\n\n      render(newNode, container);\n      expect(newNode.props.key).toBe(undefined);\n      // expect(newNode.props.hasOwnProperty('key')).toBe(false);\n      expect(container.innerHTML).toEqual('<div></div>');\n    });\n\n    it('Should keep previous key when new props dont have that property at all', () => {\n      const node = <div key=\"test\" />;\n\n      expect(node.key).toEqual('test');\n\n      render(node, container);\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      const newNode = cloneVNode(node, {\n        className: null,\n      });\n\n      expect(newNode.key).toEqual('test');\n      expect(newNode.props.key).toBe(undefined);\n      expect(newNode.props.className).toBe(undefined);\n      // expect(newNode.props.hasOwnProperty('key')).toBe(false);\n      // expect(newNode.props.hasOwnProperty('className')).toBe(false);\n      render(newNode, container);\n      expect(container.innerHTML).toEqual('<div></div>');\n    });\n  });\n\n  describe('Cloning Ref', () => {\n    function initialFunc() {}\n\n    it('Should prefer new props over cloned object', () => {\n      const node = <div ref={initialFunc} />;\n\n      expect(node.ref).toEqual(initialFunc);\n\n      render(node, container);\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      function newFunction() {}\n\n      const newNode = cloneVNode(node, {\n        ref: newFunction,\n      });\n\n      expect(newNode.ref).toEqual(newFunction);\n      // expect(newNode.props.hasOwnProperty('ref')).toBe(false);\n      expect(newNode.props.ref).toBe(undefined);\n      render(newNode, container);\n      expect(container.innerHTML).toEqual('<div></div>');\n    });\n\n    it('Should remove ref if new one is empty', () => {\n      const node = <div ref={initialFunc} />;\n\n      expect(node.ref).toEqual(initialFunc);\n\n      render(node, container);\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      const newNode = cloneVNode(node, {\n        ref: null,\n      });\n\n      expect(newNode.ref).toEqual(null);\n      // expect(newNode.props.hasOwnProperty('ref')).toBe(false);\n      expect(newNode.props.ref).toBe(undefined);\n      render(newNode, container);\n      expect(container.innerHTML).toEqual('<div></div>');\n    });\n\n    it('Should keep previous ref when new props dont have that property at all', () => {\n      const node = <div ref={initialFunc} />;\n\n      expect(node.ref).toEqual(initialFunc);\n\n      render(node, container);\n      expect(container.innerHTML).toEqual('<div></div>');\n\n      const newNode = cloneVNode(node, {\n        className: null,\n      });\n\n      expect(newNode.ref).toEqual(initialFunc);\n      // expect(newNode.props.hasOwnProperty('className')).toBe(false);\n      expect(newNode.props.className).toBe(undefined);\n      expect(newNode.className).toBe(null);\n      render(newNode, container);\n      expect(container.innerHTML).toEqual('<div></div>');\n    });\n  });\n\n  describe('without children specified', () => {\n    it('should render children one level deep', () => {\n      interface NameContainerProps {\n        children: InfernoSingleNode[];\n      }\n      class NameContainer extends Component<NameContainerProps> {\n        public render() {\n          const children = this.props.children.map((c) =>\n            cloneVNode(c as VNode, {\n              name: 'Henry',\n            }),\n          );\n\n          return <span>{children}</span>;\n        }\n      }\n\n      const NameViewer = () => {\n        return (\n          <NameContainer>\n            <div className=\"test\">\n              <span>A child that should render after the clone</span>\n            </div>\n            <div>\n              <span>A child that should render after the clone</span>\n            </div>\n          </NameContainer>\n        );\n      };\n\n      render(<NameViewer />, container);\n\n      expect(container.innerHTML)\n        .toBe(`<span><div class=\"test\" name=\"Henry\"><span>A child that should render after \\\nthe clone</span></div><div name=\"Henry\"><span>A child that should render after the clone</span></div></span>`);\n    });\n\n    it('should render children two levels deep', () => {\n      const items = [\n        { name: 'Mike Brady' },\n        { name: 'Carol Brady' },\n        { name: 'Greg Brady' },\n        { name: 'Marcia Brady' },\n      ];\n      const items2 = [{ age: 28 }, { age: 26 }, { age: 16 }, { age: 15 }];\n\n      interface Wrapper1Props {\n        children: InfernoSingleNode;\n      }\n\n      class Wrapper1 extends Component<Wrapper1Props> {\n        public render() {\n          const children = cloneVNode(this.props.children as VNode, { items });\n          return <div className=\"wrapper1\">{children}</div>;\n        }\n      }\n\n      interface Wrapper2Props {\n        items2: Array<{ age: number }>;\n        items: Array<{ name: string }>;\n        children: NormalItem[];\n      }\n\n      class Wrapper2 extends Component<Wrapper2Props> {\n        public render() {\n          const children = this.props.children.map((c) => {\n            return cloneVNode(c as any, {\n              age:\n                (c.props && c.props.index) != null\n                  ? this.props.items2[c.props.index as number].age\n                  : 'default-age',\n              name:\n                (c.props && c.props.index) != null\n                  ? this.props.items[c.props.index as number].name\n                  : 'default-name',\n              propsIndex: c.props && c.props.index,\n            });\n          });\n\n          return <div className=\"wrapper2\">{children}</div>;\n        }\n      }\n\n      interface ItemProps {\n        index?: number;\n        name?: string;\n        age?: string;\n      }\n\n      class Item extends Component<ItemProps> {\n        public render() {\n          return (\n            <span>\n              item {this.props.name} - age: {this.props.age}\n            </span>\n          );\n        }\n      }\n\n      interface NormalItemProps {\n        index?: number;\n        name?: string;\n        age?: string;\n      }\n      class NormalItem extends Component<NormalItemProps> {\n        public render() {\n          return (\n            <span>\n              Normal Item {this.props.name} - age: {this.props.age}\n            </span>\n          );\n        }\n      }\n\n      class App extends Component {\n        public render() {\n          const content: NormalItem[] = [<NormalItem />, <NormalItem />];\n\n          for (const _d of items) {\n            const idx = items.indexOf(_d);\n            content.push(<Item index={idx} />);\n          }\n\n          return (\n            <Wrapper1>\n              <Wrapper2 items={[]} items2={items2}>\n                {content}\n              </Wrapper2>\n            </Wrapper1>\n          );\n        }\n      }\n\n      render(<App />, container);\n\n      expect(container.innerHTML)\n        .toBe(`<div class=\"wrapper1\"><div class=\"wrapper2\"><span>Normal Item default-name \\\n- age: default-age</span><span>Normal Item default-name - age: default-age</span><span>item Mike Brady - age: \\\n28</span><span>item Carol Brady - age: 26</span><span>item Greg Brady - age: 16</span><span>item Marcia Brady \\\n- age: 15</span></div></div>`);\n    });\n  });\n\n  it('Should not clone all children of Component', () => {\n    // React fiddle of cloneElement https://jsfiddle.net/5wh3cfn0/\n    class Hello extends Component<{ name?: string }> {\n      public render() {\n        return <div>Hello {this.props.name}</div>;\n      }\n    }\n\n    const node1 = (\n      <Hello>\n        <span>1</span>\n      </Hello>\n    );\n    const cloned1 = cloneVNode(node1);\n\n    expect(node1.props.children).toBe(cloned1.props.children);\n    expect(node1).not.toBe(cloned1);\n    expect(node1.props).not.toBe(cloned1.props);\n\n    const node = (\n      <div>{[null, <div>1</div>, [<div>1</div>, <div>2</div>]]}</div>\n    );\n    const cloned = cloneVNode(node);\n\n    // Following assertion depends on if Inferno-compat is used or not\n    // expect(node.props.children).toBe(cloned.props.children);\n    expect(node).not.toBe(cloned);\n    expect(node.props).not.toBe(cloned.props);\n  });\n\n  it('Should be possible to clone fragment', () => {\n    const frag = (\n      <Fragment>\n        <span>1</span>\n        <span>2</span>\n      </Fragment>\n    );\n\n    render(cloneVNode(frag), container);\n\n    expect(container.innerHTML).toBe('<span>1</span><span>2</span>');\n\n    const firstChild = container.firstChild;\n\n    render(cloneVNode(frag), container);\n\n    expect(firstChild).toBe(container.firstChild);\n\n    expect(container.innerHTML).toBe('<span>1</span><span>2</span>');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-clone-vnode/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-clone-vnode/package.json",
    "content": "{\n  \"name\": \"inferno-clone-vnode\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"provides helper function to clone Inferno's vNodes\",\n  \"author\": {\n    \"name\": \"Sampo Kivistö<Havunen>\",\n    \"email\": \"sampo.kivisto@live.fi\",\n    \"url\": \"https://github.com/havunen\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-clone-vnode\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"files\": [\n    \"index.cjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"keywords\": [\n    \"babel\",\n    \"react\",\n    \"inferno\",\n    \"framework\",\n    \"interfaces\",\n    \"user interfaces\",\n    \"class\",\n    \"vdom\"\n  ],\n  \"dependencies\": {\n    \"inferno\": \"9.0.11\"\n  },\n  \"devDependencies\": {\n    \"inferno-shared\": \"9.0.11\",\n    \"inferno-vnode-flags\": \"9.0.11\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\"\n    ],\n    \"moduleName\": \"Inferno\"\n  }\n}\n"
  },
  {
    "path": "packages/inferno-clone-vnode/src/index.ts",
    "content": "import {\n  createComponentVNode,\n  createFragment,\n  createTextVNode,\n  createVNode,\n  EMPTY_OBJ,\n  normalizeProps,\n  type VNode,\n} from 'inferno';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\n\n/*\n directClone is preferred over cloneVNode and used internally also.\n This function makes Inferno backwards compatible.\n And can be tree-shaked by modern bundlers\n*/\n\n/**\n * Clones given virtual node by creating new instance of it\n * @param {VNode} vNodeToClone virtual node to be cloned\n * @param {Props=} props additional props for new virtual node\n * @param {...*} childArgs new children for new virtual node\n * @returns {VNode} new virtual node\n */\nexport function cloneVNode(vNodeToClone: VNode, props?, ...childArgs): VNode {\n  const flags = vNodeToClone.flags;\n  let children =\n    flags & VNodeFlags.Component\n      ? vNodeToClone.props?.children\n      : vNodeToClone.children;\n  const childLen = childArgs.length;\n  let className = vNodeToClone.className;\n  let key = vNodeToClone.key;\n  let ref = vNodeToClone.ref;\n  if (props) {\n    if (props.className !== void 0) {\n      className = props.className as string;\n    }\n    if (props.ref !== void 0) {\n      ref = props.ref;\n    }\n    if (props.key !== void 0) {\n      key = props.key;\n    }\n    if (props.children !== void 0) {\n      children = props.children;\n    }\n  } else {\n    props = {};\n  }\n\n  if (childLen === 1) {\n    children = childArgs[0];\n  } else if (childLen > 1) {\n    children = [];\n\n    for (let i = 0; i < childLen; i++) {\n      children.push(childArgs[i]);\n    }\n  }\n\n  props.children = children;\n\n  if (flags & VNodeFlags.Component) {\n    return createComponentVNode(\n      flags,\n      vNodeToClone.type,\n      !vNodeToClone.props && !props\n        ? EMPTY_OBJ\n        : { ...vNodeToClone.props, ...props },\n      key,\n      ref,\n    );\n  }\n\n  if (flags & VNodeFlags.Text) {\n    return createTextVNode(children);\n  }\n\n  if (flags & VNodeFlags.Fragment) {\n    return createFragment(\n      childLen === 1 ? [children] : children,\n      ChildFlags.UnknownChildren,\n      key,\n    );\n  }\n\n  return normalizeProps(\n    createVNode(\n      flags,\n      vNodeToClone.type,\n      className,\n      null,\n      ChildFlags.HasInvalidChildren,\n      { ...vNodeToClone.props, ...props },\n      key,\n      ref,\n    ),\n  );\n}\n"
  },
  {
    "path": "packages/inferno-compat/README.md",
    "content": "# inferno-compat\n\nThis module is a compatibility layer that makes React-based modules work with Inferno, without any code changes.\n\nIt provides the same exports as `react` and `react-dom`, meaning you can use your build tool of choice to drop it in where React is being depended on.\n\nDo note however, as with almost all compatability layer libraries, there is an associated cost of extra overhead. As such, you should never expect native Inferno performance when using `inferno-compat`.\n\nYou might not always need the `inferno-compat` package. Just the alias to Inferno might be enough.\n\n**Inferno-compat** adds the following features:\n\nAs in React:\n\n- ClassName is copied to props\n- Children is copied to props (for html vNodes too)\n- styles are converted from camelCase to hyphen-case runtime. You can turn off this feature by setting: `options.reactStyles = false;`\n- Empty props are always created for element vNodes\n- You can create Components based on string\n- `findDOMNOde` -method is available\n- Iterable data structures are supported\n- `Children.(map/forEach/count/only/toArray)` - methods are available\n- Html properties are transformed to inferno compatible format\n- Some form events (fe: onChange) are transformed to native alternative\n- PureComponent is available\n- `unstable_renderSubtreeIntoContainer` - method is available\n- `DOM` - factory is available\n- `unmountComponentAtNode` - method is available its same as \"render(null, container)\"\n\n## How to install?\n\nInferno-compat does not automatically install all its features. For example: If you need createElement support you should also install `inferno-create-element`.\n\nAll packages:\n\n```\nnpm install --save inferno\nnpm install --save inferno-compat\nnpm install --save inferno-clone-vnode\nnpm install --save inferno-create-element\n\n```\n\nIf you use React/lib/ReactCSSTransitionGroup.ts\n\ninstall `inferno-transition-group` package.\n\nIf you use React/lib/ReactCSSTransitionGroup.ts\n\ninstall `rc-css-transition-group-modern` package.\n\n## What is currently supported?\n\n### `react`\n\n- `React.createElement`\n- `React.cloneElement`\n- `React.Component`\n- `React.PureComponent`\n- `React.PropTypes`\n- `React.Children`\n- `React.isValidElement`\n\nNote: Inferno will not currently validate `PropTypes`\n\n### `react-dom`\n\n- `ReactDOM.render`\n- `ReactDOM.hydrate`\n- `ReactDOM.unmountComponentAtNode`\n- `ReactDOM.findDOMNode`\n- `React.DOM`\n- `React.createFactory`\n\n## Usage with Webpack\n\nUsing `inferno-compat` with Webpack is easy.\n\nAll you have to do is add an alias for `react` and `react-dom`:\n\n```js\n{\n\tresolve: {\n\t\talias: {\n\t\t\t'react': 'inferno-compat',\n\t\t\t'react-dom': 'inferno-compat'\n\t\t}\n\t}\n}\n```\n\n## Usage with Babel\n\nInstall the Babel plugin for module aliasing: `npm install --save-dev babel-plugin-module-resolver`.\n\nBabel can now alias `react` and `react-dom` to `inferno` by adding the following to your `.babelrc` file:\n\n```js\n{\n    \"plugins\": [\n        [\"module-resolver\", {\n            \"root\": [\".\"],\n            \"alias\": {\n                \"react\": \"inferno-compat\",\n                \"react-dom\": \"inferno-compat\"\n            }\n        }]\n    ]\n}\n```\n\n## Usage with Browserify\n\nUsing `inferno-compat` with Browserify is as simple as installing and configuring [aliasify](http://npm.im/aliasify).\n\nFirst, install it: `npm install --save-dev aliasify`\n\n... then in your `package.json`, configure aliasify to alias `react` and `react-dom`:\n\n```js\n{\n    // ...\n    \"aliasify\": {\n        \"aliases\": {\n            \"react\": \"inferno-compat\",\n            \"react-dom\": \"inferno-compat\"\n        }\n    }\n    // ...\n}\n```\n\n## Once Aliased\n\nWith the above Webpack or Browserify aliases in place, existing React modules should work nicely:\n\n```js\nimport React from 'react';\nimport ReactDOM from 'react-dom';\n\nclass Foo extends React.Component {\n  propTypes = {\n    a: React.PropTypes.string.isRequired,\n  };\n  render() {\n    let { a, b, children } = this.props;\n    return <div {...{ a, b }}>{children}</div>;\n  }\n}\n\nReactDOM.render(<Foo a=\"a\">test</Foo>, document.getElementById('app'));\n```\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactChildren.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\n\ndescribe('ReactChildren', function () {\n  let ReactChildren;\n\n  beforeEach(function () {\n    ReactChildren = React.Children;\n  });\n\n  it('should support identity for simple', function () {\n    const callback = jasmine.createSpy().and.callFake(function (kid, index) {\n      return kid;\n    });\n\n    const simpleKid = <span key=\"simple\" />;\n\n    // First pass children into a component to fully simulate what happens when\n    // using structures that arrive from transforms.\n\n    const instance = (\n      <div>\n        <span key=\"simple\" />\n      </div>\n    );\n    ReactChildren.forEach(instance.children, callback);\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0, jasmine.any(Array));\n    callback.calls.reset();\n    ReactChildren.map(instance.children, callback);\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0, jasmine.any(Array));\n    // expect(mappedChildren[0]).toEqual(<span key=\"simple\" />);\n  });\n\n  it('should treat single arrayless child as being in array', function () {\n    const callback = jasmine.createSpy().and.callFake(function (kid, index) {\n      return kid;\n    });\n\n    const simpleKid = <span />;\n    const instance = (\n      <div>\n        <span />\n      </div>\n    );\n    ReactChildren.forEach(instance.children, callback);\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0, jasmine.any(Array));\n    callback.calls.reset();\n    ReactChildren.map(instance.children, callback);\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0, jasmine.any(Array));\n    // expect(mappedChildren[0]).toEqual(<span key=\".0\" />);\n  });\n\n  it('should treat single child in array as expected', function () {\n    const callback = jasmine.createSpy().and.callFake(function (kid, index) {\n      return kid;\n    });\n\n    const simpleKid = <span key=\"simple\" />;\n    // Use optimization flag to avoid normalization to keep flags same... for below assertion\n    const instance = <div $HasNonKeyedChildren>{[<span key=\"simple\" />]}</div>;\n    ReactChildren.forEach(instance.children, callback);\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0, jasmine.any(Array)); // Third param is the array\n    callback.calls.reset();\n\n    ReactChildren.map(instance.children, callback);\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0, jasmine.any(Array));\n    // expect(mappedChildren[0]).toEqual(<span key=\"simple\" />);\n    // Flags dont match because its implementation detail in Inferno\n  });\n\n  it('should pass key to returned component', function () {\n    const mapFn = function (kid, index) {\n      return <div>{kid}</div>;\n    };\n    const instance = (\n      <div>\n        <span key=\"simple\" />\n      </div>\n    );\n\n    const mappedChildren = ReactChildren.map(instance.children, mapFn);\n\n    expect(ReactChildren.count(mappedChildren)).toBe(1);\n    expect(mappedChildren[0].children.key).toBe('simple');\n  });\n\n  it('should invoke callback with the right context', function () {\n    let lastContext;\n    const callback = function (kid, index) {\n      lastContext = this;\n      return this;\n    };\n\n    const scopeTester = { fooScope: 'barScope' };\n\n    const simpleKid = <span key=\"simple\" />;\n    const instance = <div>{simpleKid}</div>;\n    ReactChildren.forEach(instance.children, callback, scopeTester);\n    expect(lastContext).toEqual(scopeTester);\n\n    const mappedChildren = ReactChildren.map(\n      instance.children,\n      callback,\n      scopeTester,\n    );\n\n    expect(ReactChildren.count(mappedChildren)).toBe(1);\n    expect(mappedChildren[0]).toEqual(scopeTester);\n  });\n\n  it('ForEach should not fail if null children is provided', () => {\n    expect(React.Children.forEach(null, null, null)).toBe(undefined);\n  });\n\n  it('should not throw if key provided is a dupe with array key', function () {\n    const zero = <div />;\n    const one = <div key=\"0\" />;\n\n    const mapFn = function () {\n      return null;\n    };\n\n    const instance = (\n      <div>\n        {zero}\n        {one}\n      </div>\n    );\n\n    expect(function () {\n      ReactChildren.map(instance.props.children, mapFn);\n    }).not.toThrow();\n  });\n\n  it('should return 0 for null children', function () {\n    const numberOfChildren = ReactChildren.count(null);\n    expect(numberOfChildren).toBe(0);\n  });\n\n  it('should return 0 for undefined children', function () {\n    const numberOfChildren = ReactChildren.count(undefined);\n    expect(numberOfChildren).toBe(0);\n  });\n\n  it('should return 1 for single child', function () {\n    const simpleKid = <span key=\"simple\" />;\n    const instance = <div>{simpleKid}</div>;\n    const numberOfChildren = ReactChildren.count(instance.children);\n    expect(numberOfChildren).toBe(1);\n  });\n\n  it('should count the number of children in flat structure', function () {\n    const zero = <div key=\"keyZero\" />;\n    const one = null;\n    const two = <div key=\"keyTwo\" />;\n    const three = null;\n    const four = <div key=\"keyFour\" />;\n\n    const instance = (\n      <div>\n        {zero}\n        {one}\n        {two}\n        {three}\n        {four}\n      </div>\n    );\n    const numberOfChildren = ReactChildren.count(instance.children);\n    expect(numberOfChildren).toBe(3); // Nulls are removed in Inferno\n  });\n\n  // it('should count the number of children in nested structure', function() {\n  //   var zero = <div key=\"keyZero\" />;\n  //   var one = null;\n  //   var two = <div key=\"keyTwo\" />;\n  //   var three = null;\n  //   var four = <div key=\"keyFour\" />;\n  //   var five = <div key=\"keyFiveInner\" />;\n  //   // five is placed into a JS object with a key that is joined to the\n  //   // component key attribute.\n  //   // Precedence is as follows:\n  //   // 1. If grouped in an Object, the object key combined with `key` prop\n  //   // 2. If grouped in an Array, the `key` prop, falling back to array index\n\n  //   var instance = (\n  //     <div>{\n  //       [\n  //         ReactFragment.create({\n  //           firstHalfKey: [zero, one, two],\n  //           secondHalfKey: [three, four],\n  //           keyFive: five,\n  //         }),\n  //         null,\n  //       ]\n  //     }</div>\n  //   );\n  //   var numberOfChildren = ReactChildren.count(instance.props.children);\n  //   expect(numberOfChildren).toBe(5);\n  // });\n\n  it('should flatten children to an array', function () {\n    expect(ReactChildren.toArray(undefined)).toEqual([]);\n    expect(ReactChildren.toArray(null)).toEqual([]);\n\n    expect(ReactChildren.toArray(<div />).length).toBe(1);\n    expect(ReactChildren.toArray([<div />]).length).toBe(1);\n    expect(ReactChildren.toArray(<div />)[0].key).toBe(\n      ReactChildren.toArray([<div />])[0].key,\n    );\n\n    const flattened = ReactChildren.toArray([\n      [<div key=\"apple\" />, <div key=\"banana\" />, <div key=\"camel\" />],\n      [<div key=\"banana\" />, <div key=\"camel\" />, <div key=\"deli\" />],\n    ]);\n    expect(flattened.length).toBe(6);\n    expect(flattened[1].key).toContain('banana');\n    expect(flattened[3].key).toContain('banana');\n    // Inferno will do this when it normalizes children\n    // // expect(flattened[1].key).not.toBe(flattened[3].key);\n    //\n    // var reversed = ReactChildren.toArray([\n    //   [<div key=\"camel\" />, <div key=\"banana\" />, <div key=\"apple\" />],\n    //   [<div key=\"deli\" />, <div key=\"camel\" />, <div key=\"banana\" />],\n    // ]);\n    // expect(flattened[0].key).toBe(reversed[2].key);\n    // expect(flattened[1].key).toBe(reversed[1].key);\n    // expect(flattened[2].key).toBe(reversed[0].key);\n    // expect(flattened[3].key).toBe(reversed[5].key);\n    // expect(flattened[4].key).toBe(reversed[4].key);\n    // expect(flattened[5].key).toBe(reversed[3].key);\n    //\n    // // null/undefined/bool are all omitted\n    // expect(ReactChildren.toArray([1, 'two', null, undefined, true])).toEqual(\n    //   [1, 'two']\n    // );\n  });\n\n  it('should normalize children in forEach', function () {\n    const children = [];\n    const callback = function (child) {\n      children.push(child);\n    };\n\n    ReactChildren.forEach([false, true, undefined], callback);\n    expect(children).toEqual([null, null, null]);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactComponent.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\nimport { createComponentVNode } from 'inferno';\nimport { Wrapper } from 'inferno-test-utils';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nconst ReactDOM = React;\nlet mocks;\n\ndescribe('ReactComponent', function () {\n  let container;\n\n  function renderIntoDocument(input) {\n    return React.render(\n      createComponentVNode(VNodeFlags.ComponentClass, Wrapper, {\n        children: input,\n      }),\n      container,\n    );\n  }\n\n  beforeEach(() => {\n    mocks = {\n      getMockFunction: function () {\n        return jasmine.createSpy();\n      },\n    };\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    React.render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should throw on invalid render targets', function () {\n    const container = document.createElement('div');\n    // jQuery objects are basically arrays; people often pass them in by mistake\n    expect(function () {\n      ReactDOM.render(<div />, [container]);\n    }).toThrow();\n\n    expect(function () {\n      ReactDOM.render(<div />, null);\n    }).toThrow();\n  });\n\n  it('should support new-style refs', function () {\n    const innerObj = {};\n    const outerObj = {};\n\n    class Wrapper extends React.Component {\n      getObject() {\n        return this.props.object;\n      }\n\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    let mounted = false;\n    class Component extends React.Component {\n      render() {\n        const inner = (\n          <Wrapper object={innerObj} ref={(c) => (this.innerRef = c)} />\n        );\n        const outer = (\n          <Wrapper object={outerObj} ref={(c) => (this.outerRef = c)}>\n            {inner}\n          </Wrapper>\n        );\n        return outer;\n      }\n\n      componentDidMount() {\n        expect(this.innerRef.getObject()).toEqual(innerObj);\n        expect(this.outerRef.getObject()).toEqual(outerObj);\n        mounted = true;\n      }\n    }\n\n    const instance = <Component />;\n    renderIntoDocument(instance);\n    expect(mounted).toBe(true);\n  });\n\n  it('fires the callback after a component is rendered', function () {\n    const callback = mocks.getMockFunction();\n    const container = document.createElement('div');\n    ReactDOM.render(<div />, container, callback);\n    expect(callback.calls.count()).toBe(1);\n    ReactDOM.render(<div className=\"foo\" />, container, callback);\n    expect(callback.calls.count()).toBe(2);\n    ReactDOM.render(<span />, container, callback);\n    expect(callback.calls.count()).toBe(3);\n  });\n\n  it('throws usefully when rendering badly-typed elements', function () {\n    // spyOn(console, 'error');\n\n    const X = undefined;\n    expect(() => renderIntoDocument(<X />)).toThrow();\n\n    const Z = {};\n    expect(() => renderIntoDocument(<Z />)).toThrow();\n\n    // One warning for each element creation\n    // expect(console.error.calls.count()).toBe(3);\n  });\n\n  // other\n  it('should pass context to children when not owner', function () {\n    class Parent extends React.Component {\n      render() {\n        return (\n          <Child>\n            <Grandchild />\n          </Child>\n        );\n      }\n    }\n\n    class Child extends React.Component {\n      static childContextTypes = {\n        foo: React.PropTypes.string,\n      };\n\n      getChildContext() {\n        return {\n          foo: 'bar',\n        };\n      }\n\n      render() {\n        return React.Children.only(this.props.children);\n      }\n    }\n\n    class Grandchild extends React.Component {\n      contextTypes = {\n        foo: React.PropTypes.string,\n      };\n\n      render() {\n        return <div>{this.context.foo}</div>;\n      }\n    }\n\n    const component = renderIntoDocument(<Parent />);\n    expect(ReactDOM.findDOMNode(component).innerHTML).toBe('bar');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactComponentLifeCycle.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\nimport { createComponentVNode } from 'inferno';\nimport { Wrapper } from 'inferno-test-utils';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nconst ReactDOM = React;\n\nconst clone = function (o) {\n  return JSON.parse(JSON.stringify(o));\n};\n\nconst GET_INIT_STATE_RETURN_VAL = {\n  hasWillMountCompleted: false,\n  hasRenderCompleted: false,\n  hasDidMountCompleted: false,\n  hasWillUnmountCompleted: false,\n};\n\nconst INIT_RENDER_STATE = {\n  hasWillMountCompleted: true,\n  hasRenderCompleted: false,\n  hasDidMountCompleted: false,\n  hasWillUnmountCompleted: false,\n};\n\nconst DID_MOUNT_STATE = {\n  hasWillMountCompleted: true,\n  hasRenderCompleted: true,\n  hasDidMountCompleted: false,\n  hasWillUnmountCompleted: false,\n};\n\nconst NEXT_RENDER_STATE = {\n  hasWillMountCompleted: true,\n  hasRenderCompleted: true,\n  hasDidMountCompleted: true,\n  hasWillUnmountCompleted: false,\n};\n\nconst WILL_UNMOUNT_STATE = {\n  hasWillMountCompleted: true,\n  hasDidMountCompleted: true,\n  hasRenderCompleted: true,\n  hasWillUnmountCompleted: false,\n};\n\nconst POST_WILL_UNMOUNT_STATE = {\n  hasWillMountCompleted: true,\n  hasDidMountCompleted: true,\n  hasRenderCompleted: true,\n  hasWillUnmountCompleted: true,\n};\n\n/**\n * Every React component is in one of these life cycles.\n */\nconst ComponentLifeCycle = {\n  /**\n   * Mounted components have a DOM node representation and are capable of\n   * receiving new props.\n   */\n  MOUNTED: 'MOUNTED',\n  /**\n   * Unmounted components are inactive and cannot receive new props.\n   */\n  UNMOUNTED: 'UNMOUNTED',\n};\n\ndescribe('ReactComponentLifeCycle', function () {\n  let container;\n\n  function renderIntoDocument(input) {\n    return React.render(\n      createComponentVNode(VNodeFlags.ComponentClass, Wrapper, {\n        children: input,\n      }),\n      container,\n    );\n  }\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    React.render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should not reuse an instance when it has been unmounted', function () {\n    const container = document.createElement('div');\n    class StatefulComponent extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = {};\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n    const element = <StatefulComponent />;\n\n    const firstInstance = ReactDOM.render(element, container);\n    ReactDOM.unmountComponentAtNode(container);\n    const secondInstance = ReactDOM.render(element, container);\n    expect(firstInstance).not.toBe(secondInstance);\n  });\n\n  /**\n   * If a state update triggers rerendering that in turn fires an onDOMReady,\n   * that second onDOMReady should not fail.\n   */\n  it('it should fire onDOMReady when already in onDOMReady', function (done) {\n    const _testJournal = [];\n\n    class Child extends React.Component {\n      componentDidMount() {\n        _testJournal.push('Child:onDOMReady');\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    class SwitcherParent extends React.Component {\n      constructor(props) {\n        super(props);\n        _testJournal.push('SwitcherParent:ctr');\n        this.state = { showHasOnDOMReadyComponent: false };\n      }\n\n      componentDidMount() {\n        _testJournal.push('SwitcherParent:onDOMReady');\n        this.switchIt();\n      }\n\n      switchIt() {\n        this.setState({ showHasOnDOMReadyComponent: true });\n      }\n\n      render() {\n        return (\n          <div>\n            {this.state.showHasOnDOMReadyComponent ? <Child /> : <div> </div>}\n          </div>\n        );\n      }\n    }\n\n    const instance = <SwitcherParent />;\n    renderIntoDocument(instance);\n    setTimeout(() => {\n      expect(_testJournal).toEqual([\n        'SwitcherParent:ctr',\n        'SwitcherParent:onDOMReady',\n        'Child:onDOMReady',\n      ]);\n      done();\n    }, 20);\n  });\n\n  it('should allow update state inside of componentWillMount', function () {\n    class StatefulComponent extends React.Component {\n      componentWillMount() {\n        this.setState({ stateField: 'something' });\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const instance = <StatefulComponent />;\n    expect(function () {\n      renderIntoDocument(instance);\n    }).not.toThrow();\n  });\n\n  it('should not throw when updating an auxiliary component', function () {\n    class Tooltip extends React.Component {\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n\n      componentDidMount() {\n        this.container = document.createElement('div');\n        this.updateTooltip();\n      }\n\n      componentDidUpdate() {\n        this.updateTooltip();\n      }\n\n      updateTooltip() {\n        // Even though this.props.tooltip has an owner, updating it shouldn't\n        // throw here because it's mounted as a root component\n        ReactDOM.render(this.props.tooltip, this.container);\n      }\n    }\n\n    class Component extends React.Component {\n      render() {\n        return (\n          <Tooltip tooltip={<div>{this.props.tooltipText}</div>}>\n            {this.props.text}\n          </Tooltip>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n    ReactDOM.render(<Component text=\"uno\" tooltipText=\"one\" />, container);\n\n    // Since `instance` is a root component, we can set its props. This also\n    // makes Tooltip rerender the tooltip component, which shouldn't throw.\n    ReactDOM.render(<Component text=\"dos\" tooltipText=\"two\" />, container);\n  });\n\n  it('should allow state updates in componentDidMount', function (done) {\n    /**\n     * calls setState in an componentDidMount.\n     */\n    class SetStateInComponentDidMount extends React.Component {\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          stateField: this.props.valueToUseInitially,\n        };\n      }\n\n      componentDidMount() {\n        this.setState({ stateField: this.props.valueToUseInOnDOMReady });\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    let instance = (\n      <SetStateInComponentDidMount\n        valueToUseInitially=\"hello\"\n        valueToUseInOnDOMReady=\"goodbye\"\n      />\n    );\n    instance = renderIntoDocument(instance);\n\n    setTimeout(() => {\n      expect(instance.$LI.children.state.stateField).toBe('goodbye');\n      done();\n    }, 25);\n  });\n\n  it('should call nested lifecycle methods in the right order', function () {\n    let log;\n    const logger = function (msg) {\n      return function () {\n        // return true for shouldComponentUpdate\n        log.push(msg);\n        return true;\n      };\n    };\n    class Outer extends React.Component {\n      render() {\n        return (\n          <div>\n            <Inner x={this.props.x} />\n          </div>\n        );\n      }\n\n      componentWillMount() {\n        log.push('outer componentWillMount');\n      }\n\n      componentDidMount() {\n        log.push('outer componentDidMount');\n      }\n\n      componentWillReceiveProps() {\n        log.push('outer componentWillReceiveProps');\n      }\n\n      shouldComponentUpdate() {\n        log.push('outer shouldComponentUpdate');\n\n        return true;\n      }\n\n      componentWillUpdate() {\n        log.push('outer componentWillUpdate');\n      }\n\n      componentDidUpdate() {\n        log.push('outer componentDidUpdate');\n      }\n\n      componentWillUnmount() {\n        log.push('outer componentWillUnmount');\n      }\n    }\n\n    class Inner extends React.Component {\n      render() {\n        return <span>{this.props.x}</span>;\n      }\n\n      componentWillMount() {\n        log.push('inner componentWillMount');\n      }\n\n      componentDidMount() {\n        log.push('inner componentDidMount');\n      }\n\n      componentWillReceiveProps() {\n        log.push('inner componentWillReceiveProps');\n      }\n\n      shouldComponentUpdate() {\n        log.push('inner shouldComponentUpdate');\n\n        return true;\n      }\n\n      componentWillUpdate() {\n        log.push('inner componentWillUpdate');\n      }\n\n      componentDidUpdate() {\n        log.push('inner componentDidUpdate');\n      }\n\n      componentWillUnmount() {\n        log.push('inner componentWillUnmount');\n      }\n    }\n\n    const container = document.createElement('div');\n    log = [];\n    ReactDOM.render(<Outer x={17} />, container);\n    expect(log).toEqual([\n      'outer componentWillMount',\n      'inner componentWillMount',\n      'inner componentDidMount',\n      'outer componentDidMount',\n    ]);\n\n    log = [];\n    ReactDOM.render(<Outer x={42} />, container);\n    expect(log).toEqual([\n      'outer componentWillReceiveProps',\n      'outer shouldComponentUpdate',\n      'outer componentWillUpdate',\n      'inner componentWillReceiveProps',\n      'inner shouldComponentUpdate',\n      'inner componentWillUpdate',\n      'inner componentDidUpdate',\n      'outer componentDidUpdate',\n    ]);\n\n    log = [];\n    ReactDOM.unmountComponentAtNode(container);\n    expect(log).toEqual([\n      'outer componentWillUnmount',\n      'inner componentWillUnmount',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactCompositeComponentState.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\n\nconst ReactDOM = React;\n\ndescribe('ReactCompositeComponent-state', function () {\n  it('should batch unmounts', function () {\n    let outer;\n    class Inner extends React.Component {\n      render() {\n        return <div />;\n      }\n\n      componentWillUnmount() {\n        // This should get silently ignored (maybe with a warning), but it\n        // shouldn't break React.\n        outer.setState({ showInner: false });\n      }\n    }\n\n    class Outer extends React.Component {\n      constructor(props) {\n        super(props);\n\n        this.state = { showInner: true };\n      }\n\n      render() {\n        return <div>{this.state.showInner && <Inner />}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    outer = ReactDOM.render(<Outer />, container);\n    expect(() => {\n      ReactDOM.unmountComponentAtNode(container);\n    }).not.toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactDOM.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\nimport { createComponentVNode } from 'inferno';\nimport { Wrapper } from 'inferno-test-utils';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nconst ReactDOM = React;\nconst div = React.createFactory('div');\n\ndescribe('ReactDOM', function () {\n  let container;\n\n  function renderIntoDocument(input) {\n    return React.render(\n      createComponentVNode(VNodeFlags.ComponentClass, Wrapper, {\n        children: input,\n      }),\n      container,\n    );\n  }\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    React.render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('allows a DOM element to be used with a string', function () {\n    const element = React.createElement('div', { className: 'foo' });\n    const instance = renderIntoDocument(element);\n    expect(ReactDOM.findDOMNode(instance).tagName).toBe('DIV');\n  });\n\n  it('should allow children to be passed as an argument', function () {\n    const argDiv = renderIntoDocument(div(null, 'child'));\n    const argNode = ReactDOM.findDOMNode(argDiv);\n    expect(argNode.innerHTML).toBe('child');\n  });\n\n  it('should overwrite props.children with children argument', function () {\n    const conflictDiv = renderIntoDocument(\n      div({ children: 'fakechild' }, 'child'),\n    );\n    const conflictNode = ReactDOM.findDOMNode(conflictDiv);\n    expect(conflictNode.innerHTML).toBe('child');\n  });\n\n  /**\n   * We need to make sure that updates occur to the actual node that's in the\n   * DOM, instead of a stale cache.\n   */\n  it('should purge the DOM cache when removing nodes', function () {\n    let myDiv = renderIntoDocument(\n      <div>\n        <div key=\"theDog\" className=\"dog\" />\n        <div key=\"theBird\" className=\"bird\" />\n      </div>,\n    );\n    // Warm the cache with theDog\n    myDiv = renderIntoDocument(\n      <div>\n        <div key=\"theDog\" className=\"dogbeforedelete\" />\n        <div key=\"theBird\" className=\"bird\" />\n      </div>,\n    );\n    // Remove theDog - this should purge the cache\n    myDiv = renderIntoDocument(\n      <div>\n        <div key=\"theBird\" className=\"bird\" />\n      </div>,\n    );\n    // Now, put theDog back. It's now a different DOM node.\n    myDiv = renderIntoDocument(\n      <div>\n        <div key=\"theDog\" className=\"dog\" />\n        <div key=\"theBird\" className=\"bird\" />\n      </div>,\n    );\n    // Change the className of theDog. It will use the same element\n    myDiv = renderIntoDocument(\n      <div>\n        <div key=\"theDog\" className=\"bigdog\" />\n        <div key=\"theBird\" className=\"bird\" />\n      </div>,\n    );\n\n    const root = ReactDOM.findDOMNode(myDiv);\n    const dog = root.childNodes[0];\n    expect(dog.className).toBe('bigdog');\n  });\n\n  it('allow React.DOM factories to be called without warnings', function () {\n    spyOn(console, 'error');\n    const element = div();\n    expect(element.type).toBe('div');\n    expect(console.error.calls.count()).toBe(0);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactDOMComponent.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\n\nconst ReactDOM = React;\n\nif (global?.usingJSDOM) {\n  describe('ReactDOMComponent', function () {\n    describe('updateDOM', function () {\n      it('should handle className', function () {\n        const container = document.createElement('div');\n        ReactDOM.render(<div style={{}} />, container);\n\n        ReactDOM.render(<div className={'foo'} />, container);\n        expect(container.firstChild.className).toEqual('foo');\n        ReactDOM.render(<div className={'bar'} />, container);\n        expect(container.firstChild.className).toEqual('bar');\n        ReactDOM.render(<div className={null} />, container);\n        expect(container.firstChild.className).toEqual('');\n      });\n\n      it('should gracefully handle various style value types', function () {\n        const container = document.createElement('div');\n        ReactDOM.render(<div style={{}} />, container);\n        const stubStyle = container.firstChild.style;\n\n        // set initial style\n        const setup = {\n          display: 'block',\n          left: '1px',\n          top: '2px',\n          'font-family': 'Arial',\n        };\n        ReactDOM.render(<div style={setup} />, container);\n        expect(stubStyle.display).toEqual('block');\n        expect(stubStyle.left).toEqual('1px');\n        expect(stubStyle.fontFamily).toEqual('Arial');\n\n        // reset the style to their default state\n        const reset = { display: '', left: null, top: null, fontFamily: null };\n        ReactDOM.render(<div style={reset} />, container);\n        expect(stubStyle.display).toEqual('');\n        expect(stubStyle.left).toEqual('');\n        expect(stubStyle.top).toEqual('');\n        expect(stubStyle.fontFamily).toEqual('');\n      });\n\n      it('should update styles if initially null', function () {\n        let styles = null;\n        const container = document.createElement('div');\n        ReactDOM.render(<div style={styles} />, container);\n\n        const stubStyle = container.firstChild.style;\n\n        styles = { display: 'block' };\n\n        ReactDOM.render(<div style={styles} />, container);\n        expect(stubStyle.display).toEqual('block');\n      });\n\n      it('should update styles if updated to null multiple times', function () {\n        let styles = null;\n        const container = document.createElement('div');\n        ReactDOM.render(<div style={styles} />, container);\n\n        styles = { display: 'block' };\n        const stubStyle = container.firstChild.style;\n\n        ReactDOM.render(<div style={styles} />, container);\n        expect(stubStyle.display).toEqual('block');\n\n        ReactDOM.render(<div style={null} />, container);\n        expect(stubStyle.display).toEqual('');\n\n        ReactDOM.render(<div style={styles} />, container);\n        expect(stubStyle.display).toEqual('block');\n\n        ReactDOM.render(<div style={null} />, container);\n        expect(stubStyle.display).toEqual('');\n      });\n\n      it('should remove attributes', function () {\n        const container = document.createElement('div');\n        ReactDOM.render(<img height=\"17\" />, container);\n\n        expect(container.firstChild.hasAttribute('height')).toBe(true);\n        ReactDOM.render(<img />, container);\n        expect(container.firstChild.hasAttribute('height')).toBe(false);\n      });\n\n      it('should remove properties', function () {\n        const container = document.createElement('div');\n        ReactDOM.render(<div className=\"monkey\" />, container);\n\n        expect(container.firstChild.className).toEqual('monkey');\n        ReactDOM.render(<div />, container);\n        expect(container.firstChild.className).toEqual('');\n      });\n\n      it('should clear a single style prop when changing `style`', function () {\n        let styles = { display: 'none', color: 'red' };\n        const container = document.createElement('div');\n        ReactDOM.render(<div style={styles} />, container);\n\n        const stubStyle = container.firstChild.style;\n\n        styles = { color: 'green' };\n        ReactDOM.render(<div style={styles} />, container);\n        expect(stubStyle.display).toEqual('');\n        expect(stubStyle.color).toEqual('green');\n      });\n\n      it('should update arbitrary attributes for tags containing dashes', function () {\n        const container = document.createElement('div');\n\n        const beforeUpdate = React.createElement('x-foo-component', {}, null);\n        ReactDOM.render(beforeUpdate, container);\n\n        const afterUpdate = <x-foo-component myattr=\"myval\" />;\n        ReactDOM.render(afterUpdate, container);\n\n        expect(container.childNodes[0].getAttribute('myattr')).toBe('myval');\n      });\n\n      it('should clear all the styles when removing `style`', function () {\n        const styles = { display: 'none', color: 'red' };\n        const container = document.createElement('div');\n        ReactDOM.render(<div style={styles} />, container);\n\n        const stubStyle = container.firstChild.style;\n\n        ReactDOM.render(<div />, container);\n        expect(stubStyle.display).toEqual('');\n        expect(stubStyle.color).toEqual('');\n      });\n\n      it('should update styles when `style` changes from null to object', function () {\n        const container = document.createElement('div');\n        const styles = { color: 'red' };\n        ReactDOM.render(<div style={styles} />, container);\n        ReactDOM.render(<div />, container);\n        ReactDOM.render(<div style={styles} />, container);\n\n        const stubStyle = container.firstChild.style;\n        expect(stubStyle.color).toEqual('red');\n      });\n\n      it('should empty element when removing innerHTML', function () {\n        const container = document.createElement('div');\n        ReactDOM.render(\n          <div dangerouslySetInnerHTML={{ __html: ':)' }} />,\n          container,\n        );\n\n        expect(container.firstChild.innerHTML).toEqual(':)');\n        ReactDOM.render(<div />, container);\n        expect(container.firstChild.innerHTML).toEqual('');\n      });\n\n      it('should transition from string content to innerHTML', function () {\n        const container = document.createElement('div');\n        ReactDOM.render(<div>hello</div>, container);\n\n        expect(container.firstChild.innerHTML).toEqual('hello');\n        ReactDOM.render(\n          <div dangerouslySetInnerHTML={{ __html: 'goodbye' }} />,\n          container,\n        );\n        expect(container.firstChild.innerHTML).toEqual('goodbye');\n      });\n\n      it('should transition from innerHTML to string content', function () {\n        const container = document.createElement('div');\n        ReactDOM.render(\n          <div dangerouslySetInnerHTML={{ __html: 'bonjour' }} />,\n          container,\n        );\n\n        expect(container.firstChild.innerHTML).toEqual('bonjour');\n        ReactDOM.render(<div>adieu</div>, container);\n        expect(container.firstChild.innerHTML).toEqual('adieu');\n      });\n\n      it('should transition from innerHTML to children in nested el', function () {\n        const container = document.createElement('div');\n        ReactDOM.render(\n          <div>\n            <div dangerouslySetInnerHTML={{ __html: 'bonjour' }} />\n          </div>,\n          container,\n        );\n\n        expect(container.textContent).toEqual('bonjour');\n        ReactDOM.render(\n          <div>\n            <div>\n              <span>adieu</span>\n            </div>\n          </div>,\n          container,\n        );\n        expect(container.textContent).toEqual('adieu');\n      });\n\n      it('should transition from children to innerHTML in nested el', function () {\n        const container = document.createElement('div');\n        ReactDOM.render(\n          <div>\n            <div>\n              <span>adieu</span>\n            </div>\n          </div>,\n          container,\n        );\n\n        expect(container.textContent).toEqual('adieu');\n        ReactDOM.render(\n          <div>\n            <div dangerouslySetInnerHTML={{ __html: 'bonjour' }} />\n          </div>,\n          container,\n        );\n        expect(container.textContent).toEqual('bonjour');\n      });\n\n      it('should ignore attribute whitelist for elements with the \"is: attribute', function () {\n        const container = document.createElement('div');\n        ReactDOM.render(<button is=\"test\" cowabunga=\"chevynova\" />, container);\n        expect(container.firstChild.hasAttribute('cowabunga')).toBe(true);\n      });\n    });\n  });\n}\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactES6Class.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\n\nconst ReactDOM = React;\n\ndescribe('ReactES6Class', function () {\n  let container;\n  const freeze = function (expectation) {\n    Object.freeze(expectation);\n    return expectation;\n  };\n  let Inner;\n  let attachedListener = null;\n  let renderedName = null;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    attachedListener = null;\n    renderedName = null;\n    Inner = class extends React.Component {\n      getName() {\n        return this.props.name;\n      }\n\n      render() {\n        attachedListener = this.props.onClick;\n        renderedName = this.props.name;\n        return <div className={this.props.name} />;\n      }\n    };\n  });\n\n  function test(element, expectedTag, expectedClassName) {\n    const instance = ReactDOM.render(element, container);\n    expect(container.firstChild).not.toBeNull();\n    expect(container.firstChild.tagName).toBe(expectedTag);\n    expect(container.firstChild.className).toBe(expectedClassName);\n    return instance;\n  }\n\n  it('renders a simple stateless component with prop', function () {\n    class Foo extends React.Component {\n      render() {\n        return <Inner name={this.props.bar} />;\n      }\n    }\n    test(<Foo bar=\"foo\" />, 'DIV', 'foo');\n    test(<Foo bar=\"bar\" />, 'DIV', 'bar');\n  });\n\n  it('renders based on state using initial values in this.props', function () {\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = { bar: this.props.initialValue };\n      }\n\n      render() {\n        return <span className={this.state.bar} />;\n      }\n    }\n    test(<Foo initialValue=\"foo\" />, 'SPAN', 'foo');\n  });\n\n  it('renders based on state using props in the constructor', function () {\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = { bar: props.initialValue };\n      }\n\n      changeState() {\n        this.setState({ bar: 'bar' });\n      }\n\n      render() {\n        if (this.state.bar === 'foo') {\n          return <div className=\"foo\" />;\n        }\n        return <span className={this.state.bar} />;\n      }\n    }\n    const instance = test(<Foo initialValue=\"foo\" />, 'DIV', 'foo');\n    instance.changeState();\n    test(<Foo />, 'SPAN', 'bar');\n  });\n\n  it('renders based on context in the constructor', function () {\n    class Foo extends React.Component {\n      constructor(props, context) {\n        super(props, context);\n\n        this.state = { tag: context.tag, className: this.context.className };\n      }\n\n      render() {\n        const Tag = this.state.tag;\n        return <Tag className={this.state.className} />;\n      }\n    }\n    Foo.contextTypes = {\n      tag: React.PropTypes.string,\n      className: React.PropTypes.string,\n    };\n\n    class Outer extends React.Component {\n      getChildContext() {\n        return { tag: 'span', className: 'foo' };\n      }\n\n      render() {\n        return <Foo />;\n      }\n    }\n    Outer.childContextTypes = {\n      tag: React.PropTypes.string,\n      className: React.PropTypes.string,\n    };\n    test(<Outer />, 'SPAN', 'foo');\n  });\n\n  it('renders only once when setting state in componentWillMount', function () {\n    let renderCount = 0;\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = { bar: props.initialValue };\n      }\n\n      componentWillMount() {\n        this.setState({ bar: 'bar' });\n      }\n\n      render() {\n        renderCount++;\n        return <span className={this.state.bar} />;\n      }\n    }\n    test(<Foo initialValue=\"foo\" />, 'SPAN', 'bar');\n    expect(renderCount).toBe(1);\n  });\n\n  it('should render with null in the initial state property', function () {\n    class Foo extends React.Component {\n      constructor() {\n        super();\n        this.state = null;\n      }\n\n      render() {\n        return <span />;\n      }\n    }\n    test(<Foo />, 'SPAN', '');\n  });\n\n  it('setState through an event handler', function () {\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = { bar: props.initialValue };\n      }\n\n      handleClick() {\n        this.setState({ bar: 'bar' });\n      }\n\n      render() {\n        return (\n          <Inner name={this.state.bar} onClick={this.handleClick.bind(this)} />\n        );\n      }\n    }\n    test(<Foo initialValue=\"foo\" />, 'DIV', 'foo');\n    attachedListener();\n    expect(renderedName).toBe('bar');\n  });\n\n  it('should not implicitly bind event handlers', function () {\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.state = { bar: props.initialValue };\n      }\n\n      handleClick() {\n        this.setState({ bar: 'bar' });\n      }\n\n      render() {\n        return <Inner name={this.state.bar} onClick={this.handleClick} />;\n      }\n    }\n    test(<Foo initialValue=\"foo\" />, 'DIV', 'foo');\n    expect(attachedListener).toThrow();\n  });\n\n  it('renders using forceUpdate even when there is no state', function () {\n    class Foo extends React.Component {\n      constructor(props) {\n        super(props);\n        this.mutativeValue = props.initialValue;\n      }\n\n      handleClick() {\n        this.mutativeValue = 'bar';\n        this.forceUpdate();\n      }\n\n      render() {\n        return (\n          <Inner\n            name={this.mutativeValue}\n            onClick={this.handleClick.bind(this)}\n          />\n        );\n      }\n    }\n    test(<Foo initialValue=\"foo\" />, 'DIV', 'foo');\n    attachedListener();\n    expect(renderedName).toBe('bar');\n  });\n\n  it('will call all the normal life cycle methods', function () {\n    let lifeCycles = [];\n    class Foo extends React.Component {\n      constructor() {\n        super();\n        this.state = {};\n      }\n\n      componentWillMount() {\n        lifeCycles.push('will-mount');\n      }\n\n      componentDidMount() {\n        lifeCycles.push('did-mount');\n      }\n\n      componentWillReceiveProps(nextProps) {\n        lifeCycles.push('receive-props', nextProps);\n      }\n\n      shouldComponentUpdate(nextProps, nextState) {\n        lifeCycles.push('should-update', nextProps, nextState);\n        return true;\n      }\n\n      componentWillUpdate(nextProps, nextState) {\n        lifeCycles.push('will-update', nextProps, nextState);\n      }\n\n      componentDidUpdate(prevProps, prevState) {\n        lifeCycles.push('did-update', prevProps, prevState);\n      }\n\n      componentWillUnmount() {\n        lifeCycles.push('will-unmount');\n      }\n\n      render() {\n        return <span className={this.props.value} />;\n      }\n    }\n    test(<Foo value=\"foo\" />, 'SPAN', 'foo');\n    expect(lifeCycles).toEqual(['will-mount', 'did-mount']);\n    lifeCycles = []; // reset\n    test(<Foo value=\"bar\" />, 'SPAN', 'bar');\n    expect(lifeCycles).toEqual([\n      'receive-props',\n      freeze({ value: 'bar' }),\n      'should-update',\n      freeze({ value: 'bar' }),\n      {},\n      'will-update',\n      freeze({ value: 'bar' }),\n      {},\n      'did-update',\n      freeze({ value: 'foo' }),\n      {},\n    ]);\n    lifeCycles = []; // reset\n    ReactDOM.unmountComponentAtNode(container);\n    expect(lifeCycles).toEqual(['will-unmount']);\n  });\n\n  it('supports this.context passed via getChildContext', function () {\n    class Bar extends React.Component {\n      render() {\n        return <div className={this.context.bar} />;\n      }\n    }\n    Bar.contextTypes = { bar: React.PropTypes.string };\n    class Foo extends React.Component {\n      getChildContext() {\n        return { bar: 'bar-through-context' };\n      }\n\n      render() {\n        return <Bar />;\n      }\n    }\n    Foo.childContextTypes = { bar: React.PropTypes.string };\n    test(<Foo />, 'DIV', 'bar-through-context');\n  });\n\n  it('supports drilling through to the DOM using findDOMNode', function () {\n    const instance = test(<Inner name=\"foo\" />, 'DIV', 'foo');\n    const node = ReactDOM.findDOMNode(instance);\n    expect(node).toBe(container.firstChild);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactElement.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\nimport { createComponentVNode } from 'inferno';\nimport { Wrapper } from 'inferno-test-utils';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nconst ReactDOM = React;\n\ndescribe('ReactElement', function () {\n  class ComponentClass extends React.Component {\n    render() {\n      return React.createElement('div');\n    }\n  }\n  let originalSymbol;\n\n  beforeEach(function () {\n    // Delete the native Symbol if we have one to ensure we test the\n    // unpolyfilled environment.\n    originalSymbol = global.Symbol;\n    global.Symbol = undefined;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  let container;\n\n  function renderIntoDocument(input) {\n    return React.render(\n      createComponentVNode(VNodeFlags.ComponentClass, Wrapper, {\n        children: input,\n      }),\n      container,\n    );\n  }\n\n  afterEach(() => {\n    React.render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n    global.Symbol = originalSymbol;\n  });\n\n  // it('uses the fallback value when in an environment without Symbol', function() {\n  //   expect(<div />.$$typeof).toBe(0xeac7);\n  // });\n\n  it('returns a complete element according to spec', function () {\n    const element = React.createFactory(ComponentClass)();\n    expect(element.type).toBe(ComponentClass);\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    const expectation = {};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('allows a string to be passed as the type', function () {\n    const element = React.createFactory('div')();\n    expect(element.type).toBe('div');\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    const expectation = {};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  // it('returns an immutable element', function() {\n  //   var element = React.createFactory(ComponentClass)();\n  //   expect(() => element.type = 'div').toThrow();\n  // });\n\n  it('does not reuse the original config object', function () {\n    const config = { foo: 1 };\n    const element = React.createFactory(ComponentClass)(config);\n    expect(element.props.foo).toBe(1);\n    config.foo = 2;\n    expect(element.props.foo).toBe(1);\n  });\n\n  it('coerces the key to a string', function () {\n    const element = React.createFactory(ComponentClass)({\n      key: 12,\n      foo: '56',\n    });\n    expect(element.type).toBe(ComponentClass);\n    expect(element.key).toBe(12);\n    expect(element.ref).toBe(null);\n    const expectation = { foo: '56' };\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('merges an additional argument onto the children prop', function () {\n    spyOn(console, 'error');\n    const a = 1;\n    const element = React.createFactory(ComponentClass)(\n      {\n        children: 'text',\n      },\n      a,\n    );\n    expect(element.props.children).toBe(a);\n    expect(console.error.calls.count()).toBe(0);\n  });\n\n  it('does not override children if no rest args are provided', function () {\n    spyOn(console, 'error');\n    const element = React.createFactory(ComponentClass)({\n      children: 'text',\n    });\n    expect(element.props.children).toBe('text');\n    expect(console.error.calls.count()).toBe(0);\n  });\n\n  it('overrides children if null is provided as an argument', function () {\n    spyOn(console, 'error');\n    const element = React.createFactory(ComponentClass)(\n      {\n        children: 'text',\n      },\n      null,\n    );\n    expect(element.props.children).toBe(null);\n    expect(console.error.calls.count()).toBe(0);\n  });\n\n  it('merges rest arguments onto the children prop in an array', function () {\n    spyOn(console, 'error');\n    const a = 1;\n    const b = 2;\n    const c = 3;\n    const element = React.createFactory(ComponentClass)(null, a, b, c);\n    expect(element.props.children).toEqual([1, 2, 3]);\n    expect(console.error.calls.count()).toBe(0);\n  });\n\n  it('allows static methods to be called using the type property', function () {\n    spyOn(console, 'error');\n\n    class StaticMethodComponentClass extends React.Component {\n      constructor(props) {\n        super(props);\n\n        this.state = { valueToReturn: 'hi' };\n      }\n\n      static someStaticMethod() {\n        return 'someReturnValue';\n      }\n\n      render() {\n        return React.createElement('div');\n      }\n    }\n\n    const element = React.createElement(StaticMethodComponentClass);\n    expect(element.type.someStaticMethod()).toBe('someReturnValue');\n    expect(console.error.calls.count()).toBe(0);\n  });\n\n  it('identifies valid elements', function () {\n    class Component extends React.Component {\n      render() {\n        return React.createElement('div');\n      }\n    }\n\n    expect(React.isValidElement(React.createElement('div'))).toEqual(true);\n    expect(React.isValidElement(React.createElement(Component))).toEqual(true);\n\n    expect(React.isValidElement(null)).toEqual(false);\n    expect(React.isValidElement(true)).toEqual(false);\n    expect(React.isValidElement({})).toEqual(false);\n    expect(React.isValidElement('string')).toEqual(false);\n    expect(React.isValidElement(Component)).toEqual(false);\n    expect(React.isValidElement({ type: 'div', props: {} })).toEqual(false);\n\n    // var jsonElement = JSON.stringify(React.createElement('div'));\n    // expect(React.isValidElement(JSON.parse(jsonElement))).toBe(true);\n  });\n\n  it('allows the use of PropTypes validators in statics', function () {\n    // TODO: This test was added to cover a special case where we proxied\n    // methods. However, we don't do that any more so this test can probably\n    // be removed. Leaving it in classic as a safety precausion.\n    class Component extends React.Component {\n      render() {\n        return null;\n      }\n\n      static get specialType() {\n        return React.PropTypes.shape({ monkey: React.PropTypes.any });\n      }\n    }\n\n    expect(typeof Component.specialType).toBe('function');\n    expect(typeof Component.specialType.isRequired).toBe('function');\n  });\n\n  it('does not warn for NaN props', function () {\n    spyOn(console, 'error');\n    class Test extends React.Component {\n      render() {\n        return <div />;\n      }\n    }\n    const test = renderIntoDocument(<Test value={+undefined} />);\n    expect(test.$LI.children.props.value).toBeNaN();\n    expect(console.error.calls.count()).toBe(0);\n  });\n\n  it('identifies elements, but not JSON, if Symbols are supported', function () {\n    // Rudimentary polyfill\n    // Once all jest engines support Symbols natively we can swap this to test\n    // WITH native Symbols by default.\n    const REACT_ELEMENT_TYPE = function () {}; // fake Symbol\n    const OTHER_SYMBOL = function () {}; // another fake Symbol\n    global.Symbol = function (name) {\n      return OTHER_SYMBOL;\n    };\n    global.Symbol.for = function (key) {\n      if (key === 'react.element') {\n        return REACT_ELEMENT_TYPE;\n      }\n      return OTHER_SYMBOL;\n    };\n\n    class Component extends React.Component {\n      render() {\n        return React.createElement('div');\n      }\n    }\n\n    expect(React.isValidElement(React.createElement('div'))).toEqual(true);\n    expect(React.isValidElement(React.createElement(Component))).toEqual(true);\n\n    expect(React.isValidElement(null)).toEqual(false);\n    expect(React.isValidElement(true)).toEqual(false);\n    expect(React.isValidElement({})).toEqual(false);\n    expect(React.isValidElement('string')).toEqual(false);\n    expect(React.isValidElement(Component)).toEqual(false);\n    expect(React.isValidElement({ type: 'div', props: {} })).toEqual(false);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactElementClone.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\nimport { createComponentVNode } from 'inferno';\nimport { Wrapper } from 'inferno-test-utils';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nconst ReactDOM = React;\n\ndescribe('ReactElementClone', function () {\n  let container;\n\n  function renderIntoDocument(input) {\n    return React.render(\n      createComponentVNode(VNodeFlags.ComponentClass, Wrapper, {\n        children: input,\n      }),\n      container,\n    );\n  }\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    React.render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should clone a DOM component with new props', function () {\n    class Grandparent extends React.Component {\n      render() {\n        return <Parent child={<div className=\"child\" />} />;\n      }\n    }\n    class Parent extends React.Component {\n      render() {\n        return (\n          <div className=\"parent\">\n            {React.cloneElement(this.props.child, { className: 'xyz' })}\n          </div>\n        );\n      }\n    }\n    const component = renderIntoDocument(<Grandparent />);\n    expect(ReactDOM.findDOMNode(component).childNodes[0].className).toBe('xyz');\n  });\n\n  it('should clone a composite component with new props', function () {\n    class Child extends React.Component {\n      render() {\n        return <div className={this.props.className} />;\n      }\n    }\n    class Grandparent extends React.Component {\n      render() {\n        return <Parent child={<Child className=\"child\" />} />;\n      }\n    }\n    class Parent extends React.Component {\n      render() {\n        return (\n          <div className=\"parent\">\n            {React.cloneElement(this.props.child, { className: 'xyz' })}\n          </div>\n        );\n      }\n    }\n    const component = renderIntoDocument(<Grandparent />);\n    expect(ReactDOM.findDOMNode(component).childNodes[0].className).toBe('xyz');\n  });\n\n  it('should transfer the key property', function () {\n    class Component extends React.Component {\n      render() {\n        return null;\n      }\n    }\n    const clone = React.cloneElement(<Component />, { key: 'xyz' });\n    expect(clone.key).toBe('xyz');\n  });\n\n  it('should transfer children', function () {\n    class Component extends React.Component {\n      render() {\n        expect(this.props.children).toBe('xyz');\n        return <div />;\n      }\n    }\n\n    renderIntoDocument(React.cloneElement(<Component />, { children: 'xyz' }));\n  });\n\n  it('should shallow clone children', function () {\n    class Component extends React.Component {\n      render() {\n        expect(this.props.children).toBe('xyz');\n        return <div />;\n      }\n    }\n\n    renderIntoDocument(React.cloneElement(<Component>xyz</Component>, {}));\n  });\n\n  it('should accept children as rest arguments', function () {\n    class Component extends React.Component {\n      render() {\n        return null;\n      }\n    }\n\n    const clone = React.cloneElement(\n      <Component>xyz</Component>,\n      { children: <Component /> },\n      <div />,\n      <span />,\n    );\n\n    expect(clone.props.children).toEqual([<div />, <span />]);\n  });\n\n  it('should overwrite props', function () {\n    class Component extends React.Component {\n      render() {\n        expect(this.props.myprop).toBe('xyz');\n        return <div />;\n      }\n    }\n\n    renderIntoDocument(\n      React.cloneElement(<Component myprop=\"abc\" />, { myprop: 'xyz' }),\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactJSXElement.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\nimport { triggerEvent } from 'inferno-utils';\n\nconst ReactDOM = React;\n\ndescribe('ReactJSXElement', function () {\n  class Component extends React.Component {\n    render() {\n      return <div />;\n    }\n  }\n\n  it('returns a complete element according to spec', function () {\n    const element = <Component />;\n    expect(element.type).toBe(Component);\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    const expectation = {};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('allows a lower-case to be passed as the string type', function () {\n    const element = <div />;\n    expect(element.type).toBe('div');\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    const expectation = {};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  it('allows a string to be passed as the type', function () {\n    const TagName = 'div';\n    const element = <TagName />;\n    expect(element.type).toBe('div');\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    const expectation = {};\n    Object.freeze(expectation);\n    expect(element.props).toEqual(expectation);\n  });\n\n  // it('returns an immutable element', function() {\n  //   var element = <Component />;\n  //   expect(() => element.type = 'div').toThrow();\n  // });\n\n  it('does not reuse the object that is spread into props', function () {\n    const config = { foo: 1 };\n    const element = <Component {...config} />;\n    expect(element.props.foo).toBe(1);\n    config.foo = 2;\n    expect(element.props.foo).toBe(1);\n  });\n\n  // it('extracts key and ref from the rest of the props', function() {\n  //   var element = <Component key=\"12\" ref=\"34\" foo=\"56\" />;\n  //   expect(element.type).toBe(Component);\n  //   expect(element.key).toBe('12');\n  //   expect(element.ref).toBe('34');\n  //   var expectation = {foo:'56'};\n  //   Object.freeze(expectation);\n  //   expect(element.props).toEqual(expectation);\n  // });\n\n  // it('coerces the key to a string', function() {\n  //   var element = <Component key={12} foo=\"56\" />;\n  //   expect(element.type).toBe(Component);\n  //   expect(element.key).toBe('12');\n  //   expect(element.ref).toBe(null);\n  //   var expectation = {foo:'56'};\n  //   Object.freeze(expectation);\n  //   expect(element.props).toEqual(expectation);\n  // });\n\n  // it('merges JSX children onto the children prop', function() {\n  //   spyOn(console, 'error');\n  //   var a = 1;\n  //   var element = <Component children=\"text\">{a}</Component>;\n  //   expect(element.props.children).toBe(a);\n  //   expect(console.error.calls.count()).toBe(0);\n  // });\n\n  it('does not override children if no JSX children are provided', function () {\n    spyOn(console, 'error');\n    const element = <Component children=\"text\" />;\n    expect(element.props.children).toBe('text');\n    expect(console.error.calls.count()).toBe(0);\n  });\n\n  // it('overrides children if null is provided as a JSX child', function() {\n  //   spyOn(console, 'error');\n  //   var element = <Component children=\"text\">{null}</Component>;\n  //   expect(element.props.children).toBe(null);\n  //   expect(console.error.calls.count()).toBe(0);\n  // });\n\n  // it('merges JSX children onto the children prop in an array', function() {\n  //   spyOn(console, 'error');\n  //   var a = 1;\n  //   var b = 2;\n  //   var c = 3;\n  //   var element = <Component>{a}{b}{c}</Component>;\n  //   expect(element.props.children).toEqual([1, 2, 3]);\n  //   expect(console.error.calls.count()).toBe(0);\n  // });\n\n  it('allows static methods to be called using the type property', function () {\n    spyOn(console, 'error');\n\n    class StaticMethodComponent {\n      static someStaticMethod() {\n        return 'someReturnValue';\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const element = <StaticMethodComponent />;\n    expect(element.type.someStaticMethod()).toBe('someReturnValue');\n    expect(console.error.calls.count()).toBe(0);\n  });\n\n  it('identifies valid elements', function () {\n    expect(React.isValidElement(<div />)).toEqual(true);\n    expect(React.isValidElement(<Component />)).toEqual(true);\n\n    expect(React.isValidElement(null)).toEqual(false);\n    expect(React.isValidElement(true)).toEqual(false);\n    expect(React.isValidElement({})).toEqual(false);\n    expect(React.isValidElement('string')).toEqual(false);\n    expect(React.isValidElement(Component)).toEqual(false);\n    expect(React.isValidElement({ type: 'div', props: {} })).toEqual(false);\n  });\n\n  // it('is indistinguishable from a plain object', function() {\n  //   var element = <div className=\"foo\" />;\n  //   var object = {};\n  //   expect(element.constructor).toBe(object.constructor);\n  // });\n\n  it('should use default prop value when removing a prop', function () {\n    Component.defaultProps = { fruit: 'persimmon' };\n\n    const container = document.createElement('div');\n    const instance = ReactDOM.render(<Component fruit=\"mango\" />, container);\n    expect(instance.props.fruit).toBe('mango');\n\n    ReactDOM.render(<Component />, container);\n    expect(instance.props.fruit).toBe('persimmon');\n  });\n\n  it('Should map onDoubleClick to html native event', () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    const spy = jasmine.createSpy('spy');\n    ReactDOM.render(\n      React.createElement('a', { onDoubleClick: spy }, 'test'),\n      container,\n    );\n\n    expect(spy.calls.count()).toBe(0);\n    const element = container.querySelector('a');\n    triggerEvent('dblclick', element);\n    expect(spy.calls.count()).toBe(1);\n\n    document.body.removeChild(container);\n  });\n\n  it('Should map onDoubleClick to html native even (jsx)t', () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    const spy = jasmine.createSpy('spy');\n    const node = <a onDoubleClick={spy} />;\n    expect(node.props.onDblClick).toEqual(spy);\n    ReactDOM.render(node, container);\n\n    expect(spy.calls.count()).toBe(0);\n    const element = container.querySelector('a');\n    triggerEvent('dblclick', element);\n    expect(spy.calls.count()).toBe(1);\n\n    document.body.removeChild(container);\n  });\n\n  it('Should have input onChange event', () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    const spy = jasmine.createSpy('spy');\n    ReactDOM.render(React.createElement('input', { onChange: spy }), container);\n\n    expect(spy.calls.count()).toBe(0);\n    const element = container.querySelector('input');\n    element.value = 'test';\n    triggerEvent('input', element);\n    expect(spy.calls.count()).toBe(1);\n\n    document.body.removeChild(container);\n  });\n\n  it('Should have input onChange event (JSX)', () => {\n    const container = document.createElement('div');\n    document.body.appendChild(container);\n    const spy = jasmine.createSpy('spy');\n    ReactDOM.render(<input onChange={spy} />, container);\n\n    expect(spy.calls.count()).toBe(0);\n    const element = container.querySelector('input');\n    element.value = 'test';\n    triggerEvent('input', element);\n    expect(spy.calls.count()).toBe(1);\n\n    document.body.removeChild(container);\n  });\n\n  it('Should map onDoubleClick to html native event #1', () => {\n    const container = document.createElement('div');\n\n    ReactDOM.render(\n      React.createElement('label', { htmlFor: 'foobarID' }, 'test'),\n      container,\n    );\n\n    const element = container.querySelector('label');\n    expect(element.getAttribute('for')).toBe('foobarID');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactMount.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\n'use strict';\n\nimport React from 'inferno-compat';\n\nconst ReactDOM = React;\nconst mocks = {\n  getMockFunction: function () {\n    return jasmine.createSpy();\n  },\n};\n\ndescribe('ReactMount', function () {\n  const ReactMount = React;\n  let WebComponents;\n\n  try {\n    if (WebComponents === undefined && typeof jest !== 'undefined') {\n      // WebComponents = require('WebComponents');\n    }\n  } catch (e) {\n    // Parse error expected on engines that don't support setters\n    // or otherwise aren't supportable by the polyfill.\n    // Leave WebComponents undefined.\n  }\n\n  it('throws when given a factory', function () {\n    class Component extends React.Component {\n      render() {\n        return <div />;\n      }\n    }\n\n    expect(function () {\n      React.render(Component, document.createElement('div'));\n    }).toThrow();\n  });\n\n  it('should render different components in same root', function () {\n    const container = document.createElement('container');\n    document.body.appendChild(container);\n\n    ReactMount.render(<div />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n\n    ReactMount.render(<span />, container);\n    expect(container.firstChild.nodeName).toBe('SPAN');\n    document.body.removeChild(container);\n  });\n\n  it('should unmount and remount if the key changes', function () {\n    const container = document.createElement('container');\n\n    const mockMount = mocks.getMockFunction();\n    const mockUnmount = mocks.getMockFunction();\n\n    class Component extends React.Component {\n      componentDidMount() {\n        mockMount();\n      }\n\n      componentWillUnmount() {\n        mockUnmount();\n      }\n\n      render() {\n        return <span>{this.props.text}</span>;\n      }\n    }\n\n    expect(mockMount.calls.count()).toBe(0);\n    expect(mockUnmount.calls.count()).toBe(0);\n\n    ReactMount.render(<Component text=\"orange\" key=\"A\" />, container);\n    expect(container.firstChild.innerHTML).toBe('orange');\n    expect(mockMount.calls.count()).toBe(1);\n    expect(mockUnmount.calls.count()).toBe(0);\n\n    // If we change the key, the component is unmounted and remounted\n    ReactMount.render(<Component text=\"green\" key=\"B\" />, container);\n    expect(container.firstChild.innerHTML).toBe('green');\n    expect(mockMount.calls.count()).toBe(2);\n    expect(mockUnmount.calls.count()).toBe(1);\n\n    // But if we don't change the key, the component instance is reused\n    ReactMount.render(<Component text=\"blue\" key=\"B\" />, container);\n    expect(container.firstChild.innerHTML).toBe('blue');\n    expect(mockMount.calls.count()).toBe(2);\n    expect(mockUnmount.calls.count()).toBe(1);\n  });\n\n  it('should reuse markup if rendering to the same target twice', function () {\n    const container = document.createElement('container');\n    const instance1 = ReactDOM.render(<div />, container);\n    const instance2 = ReactDOM.render(<div />, container);\n\n    expect(instance1 === instance2).toBe(true);\n  });\n\n  // it('should warn if mounting into dirty rendered markup', function() {\n  //   var container = document.createElement('container');\n  //   container.innerHTML = ReactDOMServer.renderToString(<div />) + ' ';\n\n  //   spyOn(console, 'error');\n  //   ReactMount.render(<div />, container);\n  //   expect(console.error.calls.count()).toBe(1);\n\n  //   container.innerHTML = ' ' + ReactDOMServer.renderToString(<div />);\n\n  //   ReactMount.render(<div />, container);\n  //   expect(console.error.calls.count()).toBe(2);\n  // });\n\n  // it('should warn when mounting into document.body', function() {\n  //   var iFrame = document.createElement('iframe');\n  //   document.body.appendChild(iFrame);\n  //   spyOn(console, 'error');\n\n  //   ReactMount.render(<div />, iFrame.contentDocument.body);\n\n  //   expect(console.error.calls.count()).toBe(1);\n  //   expect(console.error.calls[0].calls.argsFor(0)[0]).toContain(\n  //     'Rendering components directly into document.body is discouraged'\n  //   );\n  // });\n\n  // it('should account for escaping on a checksum mismatch', function() {\n  //   var div = document.createElement('div');\n  //   var markup = ReactDOMServer.renderToString(\n  //     <div>This markup contains an nbsp entity: &nbsp; server text</div>);\n  //   div.innerHTML = markup;\n\n  //   spyOn(console, 'error');\n  //   ReactDOM.render(\n  //     <div>This markup contains an nbsp entity: &nbsp; client text</div>,\n  //     div\n  //   );\n  //   expect(console.error.calls.count()).toBe(1);\n  //   expect(console.error.calls[0].calls.argsFor(0)[0]).toContain(\n  //     ' (client) nbsp entity: &nbsp; client text</div>\\n' +\n  //     ' (server) nbsp entity: &nbsp; server text</div>'\n  //   );\n  // });\n\n  if (WebComponents !== undefined) {\n    it('should allow mounting/unmounting to document fragment container', function () {\n      let shadowRoot;\n      const proto = Object.create(HTMLElement.prototype, {\n        createdCallback: {\n          value: function () {\n            shadowRoot = this.createShadowRoot();\n            ReactDOM.render(<div>Hi, from within a WC!</div>, shadowRoot);\n            expect(shadowRoot.firstChild.tagName).toBe('DIV');\n            ReactDOM.render(<span>Hi, from within a WC!</span>, shadowRoot);\n            expect(shadowRoot.firstChild.tagName).toBe('SPAN');\n          },\n        },\n      });\n      proto.unmount = function () {\n        ReactDOM.unmountComponentAtNode(shadowRoot);\n      };\n      document.registerElement('x-foo', { prototype: proto });\n      const element = document.createElement('x-foo');\n      element.unmount();\n    });\n  }\n\n  it('should not crash in node cache when unmounting', function () {\n    class Component extends React.Component {\n      render() {\n        // Add refs to some nodes so that they get traversed and cached\n        return (\n          <div>\n            <div>b</div>\n            {this.props.showC && <div>c</div>}\n          </div>\n        );\n      }\n    }\n\n    const container = document.createElement('container');\n\n    ReactDOM.render(\n      <div>\n        <Component showC={false} />\n      </div>,\n      container,\n    );\n\n    // Right now, A and B are in the cache. When we add C, it won't get added to\n    // the cache (assuming markup-string mode).\n    ReactDOM.render(\n      <div>\n        <Component showC={true} />\n      </div>,\n      container,\n    );\n\n    // Remove A, B, and C. Unmounting C shouldn't cause B to get recached.\n    ReactDOM.render(<div />, container);\n\n    // Add them back -- this shouldn't cause a cached node collision.\n    ReactDOM.render(\n      <div>\n        <Component showC={true} />\n      </div>,\n      container,\n    );\n\n    ReactDOM.unmountComponentAtNode(container);\n  });\n\n  it('should not crash in node cache when unmounting, case 2', function () {\n    class A extends React.Component {\n      render() {\n        return <a key={this.props.innerKey}>{this.props.innerKey}</a>;\n      }\n    }\n    class Component extends React.Component {\n      render() {\n        return (\n          <b>\n            <i>{this.props.step === 1 && <q />}</i>\n            {this.props.step === 1 && <A innerKey={this.props.step} />}\n          </b>\n        );\n      }\n    }\n\n    const container = document.createElement('container');\n\n    ReactDOM.render(<Component step={1} />, container);\n    ReactDOM.render(<Component step={2} />, container);\n    ReactDOM.render(<Component step={1} />, container);\n    // ReactMount.getID(container.querySelector('a'));\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactMountDestruction.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\n\nconst ReactDOM = React;\n\ndescribe('ReactMount', function () {\n  it('should destroy a react root upon request', function () {\n    const mainContainerDiv = document.createElement('div');\n    document.body.appendChild(mainContainerDiv);\n\n    const instanceOne = <div className=\"firstReactDiv\" />;\n    const firstRootDiv = document.createElement('div');\n    mainContainerDiv.appendChild(firstRootDiv);\n    ReactDOM.render(instanceOne, firstRootDiv);\n\n    const instanceTwo = <div className=\"secondReactDiv\" />;\n    const secondRootDiv = document.createElement('div');\n    mainContainerDiv.appendChild(secondRootDiv);\n    ReactDOM.render(instanceTwo, secondRootDiv);\n\n    // Test that two react roots are rendered in isolation\n    expect(firstRootDiv.firstChild.className).toBe('firstReactDiv');\n    expect(secondRootDiv.firstChild.className).toBe('secondReactDiv');\n\n    // Test that after unmounting each, they are no longer in the document.\n    ReactDOM.unmountComponentAtNode(firstRootDiv);\n    expect(firstRootDiv.firstChild).toBeNull();\n    ReactDOM.unmountComponentAtNode(secondRootDiv);\n    expect(secondRootDiv.firstChild).toBeNull();\n    document.body.removeChild(mainContainerDiv);\n  });\n\n  // it('should warn when unmounting a non-container root node', function() {\n  //   var mainContainerDiv = document.createElement('div');\n\n  //   var component =\n  //     <div>\n  //       <div />\n  //     </div>;\n  //   ReactDOM.render(component, mainContainerDiv);\n\n  //   // Test that unmounting at a root node gives a helpful warning\n  //   var rootDiv = mainContainerDiv.firstChild;\n  //   spyOn(console, 'error');\n  //   ReactDOM.unmountComponentAtNode(rootDiv);\n  //   expect(console.error.calls.count()).toBe(1);\n  //   expect(console.error.mostRecentCall.calls.argsFor(0)).toBe(\n  //     'Warning: unmountComponentAtNode(): The node you\\'re attempting to ' +\n  //     'unmount was rendered by React and is not a top-level container. You ' +\n  //     'may have accidentally passed in a React root node instead of its ' +\n  //     'container.'\n  //   );\n  // });\n\n  // it('should warn when unmounting a non-container, non-root node', function() {\n  //   var mainContainerDiv = document.createElement('div');\n\n  //   var component =\n  //     <div>\n  //       <div>\n  //         <div />\n  //       </div>\n  //     </div>;\n  //   ReactDOM.render(component, mainContainerDiv);\n\n  //   // Test that unmounting at a non-root node gives a different warning\n  //   var nonRootDiv = mainContainerDiv.firstChild.firstChild;\n  //   spyOn(console, 'error');\n  //   ReactDOM.unmountComponentAtNode(nonRootDiv);\n  //   expect(console.error.calls.count()).toBe(1);\n  //   expect(console.error.mostRecentCall.calls.argsFor(0)).toBe(\n  //     'Warning: unmountComponentAtNode(): The node you\\'re attempting to ' +\n  //     'unmount was rendered by React and is not a top-level container. ' +\n  //     'Instead, have the parent component update its state and rerender in ' +\n  //     'order to remove this component.'\n  //   );\n  // });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactMultiChild.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\n\nconst ReactDOM = React;\nconst mocks = {\n  getMockFunction: function () {\n    return jasmine.createSpy();\n  },\n};\n\ndescribe('ReactMultiChild', function () {\n  describe('reconciliation', function () {\n    it('should update children when possible', function () {\n      const container = document.createElement('div');\n\n      const mockMount = mocks.getMockFunction();\n      const mockUpdate = mocks.getMockFunction();\n      const mockUnmount = mocks.getMockFunction();\n\n      class MockComponent extends React.Component {\n        componentDidMount() {\n          mockMount();\n        }\n\n        componentDidUpdate() {\n          mockUpdate();\n        }\n\n        componentWillUnmount() {\n          mockUnmount();\n        }\n\n        render() {\n          return <span />;\n        }\n      }\n\n      expect(mockMount.calls.count()).toBe(0);\n      expect(mockUpdate.calls.count()).toBe(0);\n      expect(mockUnmount.calls.count()).toBe(0);\n\n      ReactDOM.render(\n        <div>\n          <MockComponent />\n        </div>,\n        container,\n      );\n\n      expect(mockMount.calls.count()).toBe(1);\n      expect(mockUpdate.calls.count()).toBe(0);\n      expect(mockUnmount.calls.count()).toBe(0);\n\n      ReactDOM.render(\n        <div>\n          <MockComponent />\n        </div>,\n        container,\n      );\n\n      expect(mockMount.calls.count()).toBe(1);\n      expect(mockUpdate.calls.count()).toBe(1);\n      expect(mockUnmount.calls.count()).toBe(0);\n    });\n\n    it('should replace children with different constructors', function () {\n      const container = document.createElement('div');\n\n      const mockMount = mocks.getMockFunction();\n      const mockUnmount = mocks.getMockFunction();\n\n      class MockComponent extends React.Component {\n        componentDidMount() {\n          mockMount();\n        }\n\n        componentWillUnmount() {\n          mockUnmount();\n        }\n\n        render() {\n          return <span />;\n        }\n      }\n\n      expect(mockMount.calls.count()).toBe(0);\n      expect(mockUnmount.calls.count()).toBe(0);\n\n      ReactDOM.render(\n        <div>\n          <MockComponent />\n        </div>,\n        container,\n      );\n\n      expect(mockMount.calls.count()).toBe(1);\n      expect(mockUnmount.calls.count()).toBe(0);\n\n      ReactDOM.render(\n        <div>\n          <span />\n        </div>,\n        container,\n      );\n\n      expect(mockMount.calls.count()).toBe(1);\n      expect(mockUnmount.calls.count()).toBe(1);\n    });\n\n    it('should NOT replace children with different owners', function () {\n      const container = document.createElement('div');\n\n      const mockMount = mocks.getMockFunction();\n      const mockUnmount = mocks.getMockFunction();\n\n      class MockComponent extends React.Component {\n        componentDidMount() {\n          mockMount();\n        }\n\n        componentWillUnmount() {\n          mockUnmount();\n        }\n\n        render() {\n          return <span />;\n        }\n      }\n\n      class WrapperComponent extends React.Component {\n        render() {\n          return this.props.children || <MockComponent />;\n        }\n      }\n\n      expect(mockMount.calls.count()).toBe(0);\n      expect(mockUnmount.calls.count()).toBe(0);\n\n      ReactDOM.render(<WrapperComponent />, container);\n\n      expect(mockMount.calls.count()).toBe(1);\n      expect(mockUnmount.calls.count()).toBe(0);\n\n      ReactDOM.render(\n        <WrapperComponent>\n          <MockComponent />\n        </WrapperComponent>,\n        container,\n      );\n\n      expect(mockMount.calls.count()).toBe(1);\n      expect(mockUnmount.calls.count()).toBe(0);\n    });\n\n    it('should replace children with different keys', function () {\n      const container = document.createElement('div');\n\n      const mockMount = mocks.getMockFunction();\n      const mockUnmount = mocks.getMockFunction();\n\n      class MockComponent extends React.Component {\n        componentDidMount() {\n          mockMount();\n        }\n\n        componentWillUnmount() {\n          mockUnmount();\n        }\n\n        render() {\n          return <span />;\n        }\n      }\n\n      expect(mockMount.calls.count()).toBe(0);\n      expect(mockUnmount.calls.count()).toBe(0);\n\n      ReactDOM.render(\n        <div>\n          <MockComponent key=\"A\" />\n        </div>,\n        container,\n      );\n\n      expect(mockMount.calls.count()).toBe(1);\n      expect(mockUnmount.calls.count()).toBe(0);\n\n      ReactDOM.render(\n        <div>\n          <MockComponent key=\"B\" />\n        </div>,\n        container,\n      );\n\n      expect(mockMount.calls.count()).toBe(2);\n      expect(mockUnmount.calls.count()).toBe(1);\n    });\n  });\n\n  // describe('innerHTML', function() {\n  //   var setInnerHTML;\n\n  //   // Only run this suite if `Element.prototype.innerHTML` can be spied on.\n  //   var innerHTMLDescriptor = Object.getOwnPropertyDescriptor(\n  //     Element.prototype,\n  //     'innerHTML'\n  //   );\n  //   if (!innerHTMLDescriptor) {\n  //     return;\n  //   }\n\n  //   beforeEach(function() {\n  //     var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');\n  //     ReactDOMFeatureFlags.useCreateElement = false;\n\n  //     Object.defineProperty(Element.prototype, 'innerHTML', {\n  //       set: setInnerHTML = jasmine.createSpy().andCallFake(\n  //         innerHTMLDescriptor.set\n  //       ),\n  //     });\n  //   });\n\n  //   it('should only set `innerHTML` once on update', function() {\n  //     var container = document.createElement('div');\n\n  //     ReactDOM.render(\n  //       <div>\n  //         <p><span /></p>\n  //         <p><span /></p>\n  //         <p><span /></p>\n  //       </div>,\n  //       container\n  //     );\n  //     // Warm the cache used by `getMarkupWrap`.\n  //     ReactDOM.render(\n  //       <div>\n  //         <p><span /><span /></p>\n  //         <p><span /><span /></p>\n  //         <p><span /><span /></p>\n  //       </div>,\n  //       container\n  //     );\n  //     expect(setInnerHTML).toHaveBeenCalled();\n  //     var callCountOnMount = setInnerHTML.calls.count();\n\n  //     ReactDOM.render(\n  //       <div>\n  //         <p><span /><span /><span /></p>\n  //         <p><span /><span /><span /></p>\n  //         <p><span /><span /><span /></p>\n  //       </div>,\n  //       container\n  //     );\n  //     expect(setInnerHTML.calls.count()).toBe(callCountOnMount + 1);\n  //   });\n  // });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactPureComponent.spec.jsx",
    "content": "/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\n\nconst ReactDOM = React;\n\ndescribe('ReactPureComponent', function () {\n  it('should render', function () {\n    let renders = 0;\n    class Component extends React.PureComponent {\n      constructor() {\n        super();\n        this.state = { type: 'mushrooms' };\n      }\n\n      render() {\n        renders++;\n        return <div>{this.props.text[0]}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    let text;\n    let component;\n\n    text = ['porcini'];\n    component = ReactDOM.render(<Component text={text} />, container);\n    expect(container.textContent).toBe('porcini');\n    expect(renders).toBe(1);\n\n    text = ['morel'];\n    component = ReactDOM.render(<Component text={text} />, container);\n    expect(container.textContent).toBe('morel');\n    expect(renders).toBe(2);\n\n    text[0] = 'portobello';\n    component = ReactDOM.render(<Component text={text} />, container);\n    expect(container.textContent).toBe('morel');\n    expect(renders).toBe(2);\n\n    // Setting state without changing it doesn't cause a rerender.\n    component.setState({ type: 'mushrooms' });\n    expect(container.textContent).toBe('morel');\n    expect(renders).toBe(2);\n\n    // But changing state does.\n    component.setState({ type: 'portobello mushrooms' });\n    expect(container.textContent).toBe('portobello');\n    expect(renders).toBe(3);\n  });\n\n  it('should render when props or state mismatch in prop count', function () {\n    let renders = 0;\n    class Component extends React.PureComponent {\n      constructor() {\n        super();\n        this.state = { type: 'mushrooms' };\n      }\n\n      shouldComponentUpdate(nextProps, state) {\n        return super.shouldComponentUpdate(nextProps, state);\n      }\n\n      render() {\n        renders++;\n        return <div>{this.props.text[0]}</div>;\n      }\n    }\n\n    const container = document.createElement('div');\n    let text;\n    let component;\n\n    text = ['porcini'];\n    component = ReactDOM.render(\n      <Component foo={'bar'} text={text} />,\n      container,\n    );\n    expect(container.textContent).toBe('porcini');\n    expect(renders).toBe(1);\n\n    component = ReactDOM.render(<Component text={text} />, container);\n    expect(container.textContent).toBe('porcini');\n    expect(renders).toBe(2);\n  });\n\n  it('can override shouldComponentUpdate', function () {\n    let renders = 0;\n    class Component extends React.PureComponent {\n      render() {\n        renders++;\n        return <div />;\n      }\n\n      shouldComponentUpdate() {\n        return true;\n      }\n    }\n    const container = document.createElement('div');\n    ReactDOM.render(<Component />, container);\n    ReactDOM.render(<Component />, container);\n    expect(renders).toBe(2);\n  });\n\n  it('extends React.Component', function () {\n    let renders = 0;\n    class Component extends React.PureComponent {\n      render() {\n        expect(this instanceof React.Component).toBe(true);\n        expect(this instanceof React.PureComponent).toBe(true);\n        renders++;\n        return <div />;\n      }\n    }\n    ReactDOM.render(<Component />, document.createElement('div'));\n    expect(renders).toBe(1);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/ReactStatelessComponent.spec.jsx",
    "content": "/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\nimport { createComponentVNode } from 'inferno';\nimport { Wrapper } from 'inferno-test-utils';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nconst ReactDOM = React;\n\nfunction StatelessComponent(props) {\n  return <div>{props.name}</div>;\n}\n\ndescribe('ReactStatelessComponent', function () {\n  let container;\n\n  function renderIntoDocument(input) {\n    return React.render(\n      createComponentVNode(VNodeFlags.ComponentClass, Wrapper, {\n        children: input,\n      }),\n      container,\n    );\n  }\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    React.render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should render stateless component', function () {\n    const el = document.createElement('div');\n    ReactDOM.render(<StatelessComponent name=\"A\" />, el);\n\n    expect(el.textContent).toBe('A');\n  });\n\n  it('should update stateless component', function () {\n    class Parent extends React.Component {\n      render() {\n        return <StatelessComponent {...this.props} />;\n      }\n    }\n\n    const el = document.createElement('div');\n    ReactDOM.render(<Parent name=\"A\" />, el);\n    expect(el.textContent).toBe('A');\n\n    ReactDOM.render(<Parent name=\"B\" />, el);\n    expect(el.textContent).toBe('B');\n  });\n\n  it('should unmount stateless component', function () {\n    const container = document.createElement('div');\n\n    ReactDOM.render(<StatelessComponent name=\"A\" />, container);\n    expect(container.textContent).toBe('A');\n\n    ReactDOM.unmountComponentAtNode(container);\n    expect(container.textContent).toBe('');\n  });\n\n  it('should pass context thru stateless component', function () {\n    class Child extends React.Component {\n      static contextTypes = {\n        test: React.PropTypes.string.isRequired,\n      };\n\n      render() {\n        return <div>{this.context.test}</div>;\n      }\n    }\n\n    function Parent() {\n      return <Child />;\n    }\n\n    class GrandParent extends React.Component {\n      static childContextTypes = {\n        test: React.PropTypes.string.isRequired,\n      };\n\n      getChildContext() {\n        return { test: this.props.test };\n      }\n\n      render() {\n        return <Parent />;\n      }\n    }\n\n    const el = document.createElement('div');\n    ReactDOM.render(<GrandParent test=\"test\" />, el);\n\n    expect(el.textContent).toBe('test');\n\n    ReactDOM.render(<GrandParent test=\"mest\" />, el);\n\n    expect(el.textContent).toBe('mest');\n  });\n\n  it('should warn when stateless component returns array', function () {\n    spyOn(console, 'error');\n    function NotAComponent() {\n      return [<div />, <div />];\n    }\n    expect(function () {\n      React.render(\n        <div>\n          <NotAComponent />\n        </div>,\n      );\n    }).toThrow();\n  });\n\n  it('should receive context', function () {\n    class Parent extends React.Component {\n      static childContextTypes = {\n        lang: React.PropTypes.string,\n      };\n\n      getChildContext() {\n        return { lang: 'en' };\n      }\n\n      render() {\n        return <Child />;\n      }\n    }\n\n    function Child(props, context) {\n      return <div>{context.lang}</div>;\n    }\n    Child.contextTypes = { lang: React.PropTypes.string };\n\n    const el = document.createElement('div');\n    ReactDOM.render(<Parent />, el);\n    expect(el.textContent).toBe('en');\n  });\n\n  it('should work with arrow functions', function () {\n    let Child = function () {\n      return <div />;\n    };\n    // Will create a new bound function without a prototype, much like a native\n    // arrow function.\n    Child = Child.bind(this);\n\n    expect(() => renderIntoDocument(<Child />)).not.toThrow();\n  });\n\n  it('should allow simple functions to return null', function () {\n    const Child = function () {\n      return null;\n    };\n    expect(() => renderIntoDocument(<Child />)).not.toThrow();\n  });\n\n  it('should allow simple functions to return false', function () {\n    function Child() {\n      return false;\n    }\n    expect(() => renderIntoDocument(<Child />)).not.toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/SelectValueElement.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\nimport { createComponentVNode } from 'inferno';\nimport { Wrapper } from 'inferno-test-utils';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nconst ReactDOM = React;\n\ndescribe('Render Select with multiple values', function () {\n  let container;\n\n  function renderIntoDocument(input) {\n    return React.render(\n      createComponentVNode(VNodeFlags.ComponentClass, Wrapper, {\n        children: input,\n      }),\n      container,\n    );\n  }\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    React.render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  class Component extends React.Component {\n    constructor(props, context) {\n      super(props, context);\n      this.state = { selectedValue: [1, 3, 4] };\n    }\n\n    render() {\n      return (\n        <div>\n          <select value={this.state.selectedValue} id=\"selectNode\" multiple>\n            <option value={1}>1</option>\n            <option value={2}>2</option>\n            <option value={3}>3</option>\n            <option value={4}>4</option>\n          </select>\n          {this.state.selectedValue}\n        </div>\n      );\n    }\n  }\n\n  it('should mark correct option as selected', function () {\n    const instance = renderIntoDocument(<Component />);\n    const root = ReactDOM.findDOMNode(instance);\n    expect(root.childNodes[0].options[0].selected).toBe(true);\n    expect(root.childNodes[0].options[1].selected).toBe(false);\n    expect(root.childNodes[0].options[2].selected).toBe(true);\n    expect(root.childNodes[0].options[3].selected).toBe(true);\n  });\n});\n\ndescribe('Render Select with single value', function () {\n  let container;\n  function renderIntoDocument(input) {\n    return React.render(\n      createComponentVNode(VNodeFlags.ComponentClass, Wrapper, {\n        children: input,\n      }),\n      container,\n    );\n  }\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    React.render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  class Component extends React.Component {\n    constructor(props, context) {\n      super(props, context);\n      this.state = { selectedValue: 2 };\n    }\n\n    render() {\n      return (\n        <div>\n          <select value={this.state.selectedValue} id=\"selectNode\">\n            <option value={1}>1</option>\n            <option value={2}>2</option>\n            <option value={3}>3</option>\n            <option value={4}>4</option>\n          </select>\n          {this.state.selectedValue}\n        </div>\n      );\n    }\n  }\n\n  it('should mark correct option as selected', function () {\n    const instance = renderIntoDocument(<Component />);\n    const root = ReactDOM.findDOMNode(instance);\n\n    expect(root.childNodes[0].options[0].selected).toBe(false);\n    expect(root.childNodes[0].options[1].selected).toBe(true);\n    expect(root.childNodes[0].options[2].selected).toBe(false);\n    expect(root.childNodes[0].options[3].selected).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/clonevnode.spec.tsx",
    "content": "import { createVNode, directClone } from 'inferno-compat';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\n\ndescribe('directClone inferno-compat', () => {\n  it('Should not lose props when cloning multiple times', () => {\n    const vNode = createVNode(\n      VNodeFlags.HtmlElement,\n      'stop',\n      null,\n      null,\n      ChildFlags.HasInvalidChildren,\n      {\n        offset: 0,\n        stopColor: 'white',\n        stopOpacity: 0.5,\n      },\n      null,\n      null,\n    );\n\n    const cloned = directClone(vNode);\n    const cloned2 = directClone(cloned);\n\n    expect(cloned2.props['stop-color']).toBe('white');\n    expect(cloned2.props['stop-opacity']).toBe(0.5);\n    expect(cloned2.props.offset).toBe(0);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/compat_children.spec.tsx",
    "content": "import {\n  Component,\n  createElement,\n  render,\n} from 'inferno-compat';\nimport {isValidElement} from 'inferno-shared'\n\ndescribe('Compat Children', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  function renderCompatTestElement(element) {\n    render(element, container);\n  }\n\n  describe('using createElement', () => {\n    it('should create a VNode with the correct className', function () {\n      const element = createElement('div', { className: 'foo', test: 'hi' });\n      expect(element.className).toBe('foo');\n      expect(element.props).toEqual({ test: 'hi', className: 'foo' });\n    });\n\n    it('Should render element with a text string', function () {\n      const element = createElement('div', null, 'body text');\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe('<div>body text</div>');\n    });\n\n    it('Should render element with an array of one text string', function () {\n      const element = createElement('div', null, ['body text']);\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe('<div>body text</div>');\n    });\n\n    it('Should render element with an array of two text strings', function () {\n      const element = createElement('div', null, ['first text', 'second text']);\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe('<div>first textsecond text</div>');\n    });\n\n    it('Should render element with child element', function () {\n      const child = createElement('span', null, 'child body text');\n      expect(isValidElement(child)).toBe(true);\n\n      const element = createElement('div', null, child);\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe(\n        '<div><span>child body text</span></div>',\n      );\n    });\n\n    it('Should render element with an array of one child element', function () {\n      const child = createElement('span', null, 'child body text');\n      expect(isValidElement(child)).toBe(true);\n\n      const element = createElement('div', null, [child]);\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe(\n        '<div><span>child body text</span></div>',\n      );\n    });\n\n    it('Should render element with an array of two child elements', function () {\n      const first_child = createElement('span', null, 'first text');\n      expect(isValidElement(first_child)).toBe(true);\n\n      const second_child = createElement('span', null, 'second text');\n      expect(isValidElement(second_child)).toBe(true);\n\n      const element = createElement('div', null, [first_child, second_child]);\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe(\n        '<div><span>first text</span><span>second text</span></div>',\n      );\n    });\n\n    it('Should render element with an array of a string and a child element', function () {\n      const second_child = createElement('span', null, 'second text');\n      expect(isValidElement(second_child)).toBe(true);\n\n      const element = createElement('div', null, ['first text', second_child]);\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe(\n        '<div>first text<span>second text</span></div>',\n      );\n    });\n\n    // Test Iterator support, skip if it is not supported in browser\n\n    if (typeof Symbol?.iterator !== 'undefined') {\n      function arrayAsBasicIterator(array) {\n        return {\n          [Symbol.iterator]: function () {\n            let idx = 0;\n            return {\n              next() {\n                if (idx < array.length) {\n                  return { value: array[idx++], done: false };\n                } else {\n                  return { done: true };\n                }\n              },\n            };\n          },\n        };\n      }\n\n      it('Should render element with an iterable of one text string', function () {\n        const iterable = arrayAsBasicIterator(['generated body text']);\n        const element = createElement('div', null, iterable);\n        expect(isValidElement(element)).toBe(true);\n\n        renderCompatTestElement(element);\n\n        expect(container.innerHTML).toBe('<div>generated body text</div>');\n      });\n\n      it('Should render element with an iterable of one child element', function () {\n        const child = createElement('span', null, 'generated child body text');\n        expect(isValidElement(child)).toBe(true);\n\n        const iterable = arrayAsBasicIterator([child]);\n        const element = createElement('div', null, iterable);\n        expect(isValidElement(element)).toBe(true);\n\n        renderCompatTestElement(element);\n\n        expect(container.innerHTML).toBe(\n          '<div><span>generated child body text</span></div>',\n        );\n      });\n\n      it('Should render element with an iterable of a child element and a string', function () {\n        const child = createElement('span', null, 'generated child body text');\n        expect(isValidElement(child)).toBe(true);\n\n        const iterable = arrayAsBasicIterator([child, 'generated body text']);\n        const element = createElement('div', null, iterable);\n        expect(isValidElement(element)).toBe(true);\n\n        renderCompatTestElement(element);\n\n        expect(container.innerHTML).toBe(\n          '<div><span>generated child body text</span>generated body text</div>',\n        );\n      });\n    }\n  });\n\n  describe('using JSX', () => {\n    it('should create a VNode with the correct className', function () {\n      // @ts-expect-error\n      // eslint-disable-next-line inferno/no-unknown-property\n      const element = <div className=\"foo\" test=\"hi\" />;\n      expect(element.className).toBe('foo');\n      expect(element.props).toEqual({ test: 'hi', className: 'foo' });\n    });\n\n    it('Should render element with a text string', function () {\n      const element = <div>body text</div>;\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe('<div>body text</div>');\n    });\n\n    it('Should render element with an array of one text string', function () {\n      const element = <div>{['body text']}</div>;\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe('<div>body text</div>');\n    });\n\n    it('Should render element with an array of two text strings', function () {\n      const element = <div>{['first text', 'second text']}</div>;\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe('<div>first textsecond text</div>');\n    });\n\n    it('Should render element with child element', function () {\n      const child = <span>{'child body text'}</span>;\n      expect(isValidElement(child)).toBe(true);\n\n      const element = <div>{child}</div>;\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe(\n        '<div><span>child body text</span></div>',\n      );\n    });\n\n    it('Should render element with an array of one child element', function () {\n      const child = <span>child body text</span>;\n      expect(isValidElement(child)).toBe(true);\n\n      const element = <div>{[child]}</div>;\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe(\n        '<div><span>child body text</span></div>',\n      );\n    });\n\n    it('Should render element with an array of two child elements', function () {\n      const first_child = <span>first text</span>;\n      expect(isValidElement(first_child)).toBe(true);\n\n      const second_child = <span>second text</span>;\n      expect(isValidElement(second_child)).toBe(true);\n\n      const element = <div>{[first_child, second_child]}</div>;\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe(\n        '<div><span>first text</span><span>second text</span></div>',\n      );\n    });\n\n    it('Should render element with an array of a string and a child element', function () {\n      const second_child = <span>second text</span>;\n      expect(isValidElement(second_child)).toBe(true);\n\n      const element = <div>{['first text', second_child]}</div>;\n      expect(isValidElement(element)).toBe(true);\n\n      renderCompatTestElement(element);\n\n      expect(container.innerHTML).toBe(\n        '<div>first text<span>second text</span></div>',\n      );\n    });\n\n    // Test Iterator support, skip if it is not supported in browser\n\n    if (typeof Symbol?.iterator !== 'undefined') {\n      function arrayAsBasicIterator(array) {\n        return {\n          [Symbol.iterator]: function () {\n            let idx = 0;\n            return {\n              next() {\n                if (idx < array.length) {\n                  return { value: array[idx++], done: false };\n                } else {\n                  return { done: true };\n                }\n              },\n            };\n          },\n        };\n      }\n\n      it('Should render element with an iterable of one text string', function () {\n        const iterable = arrayAsBasicIterator(['generated body text']);\n        const element = <div>{iterable}</div>;\n        expect(isValidElement(element)).toBe(true);\n\n        renderCompatTestElement(element);\n\n        expect(container.innerHTML).toBe('<div>generated body text</div>');\n      });\n\n      it('Should render element with an iterable of one child element', function () {\n        const child = <span>{'generated child body text'}</span>;\n        expect(isValidElement(child)).toBe(true);\n\n        const iterable = arrayAsBasicIterator([child]);\n        const element = createElement('div', null, iterable);\n        expect(isValidElement(element)).toBe(true);\n\n        renderCompatTestElement(element);\n\n        expect(container.innerHTML).toBe(\n          '<div><span>generated child body text</span></div>',\n        );\n      });\n\n      it('Should render element with an iterable of a child element and a string', function () {\n        const child = <span>generated child body text</span>;\n        expect(isValidElement(child)).toBe(true);\n\n        const iterable = arrayAsBasicIterator([child, 'generated body text']);\n        const element = createElement('div', null, iterable);\n        expect(isValidElement(element)).toBe(true);\n\n        renderCompatTestElement(element);\n\n        expect(container.innerHTML).toBe(\n          '<div><span>generated child body text</span>generated body text</div>',\n        );\n      });\n    }\n  });\n\n  // Ref: https://github.com/infernojs/inferno/issues/513\n  describe('String components (React compat)', () => {\n    it('Should render a string div', () => {\n      const Div = 'div';\n      render(<Div>Hello World</Div>, container);\n      expect(container.innerHTML).toBe('<div>Hello World</div>');\n    });\n  });\n\n  describe('Iterables', () => {\n    it('Should render 0 as \"0\" text node (Array)', () => {\n      class Hello extends Component {\n        render() {\n          return <div>Hello {0} Inferno</div>;\n        }\n      }\n\n      render(<Hello />, container);\n\n      expect(container.innerHTML).toBe('<div>Hello 0 Inferno</div>');\n    });\n\n    const g = typeof window === 'undefined' ? global : window;\n    const hasSymbolSupport = typeof g.Symbol !== 'undefined';\n\n    if (hasSymbolSupport && 'Set' in window) {\n      it('Should render 0 as \"0\" text node (Set)', () => {\n        class Hello extends Component {\n          render() {\n            const set = new Set();\n\n            set.add('Hello ');\n            set.add(0);\n            set.add(' Inferno');\n\n            return <div>{set}</div>;\n          }\n        }\n\n        render(<Hello />, container);\n\n        expect(container.innerHTML).toBe('<div>Hello 0 Inferno</div>');\n      });\n    }\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/findDOMNodes.spec.jsx",
    "content": "import { Component, findDOMNode, render } from 'inferno-compat';\n\ndescribe('findDOMNodes (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('various tests to see if the DOM node is right for the component', () => {\n    let instance1;\n    let instance2;\n    let instance3;\n    let ref;\n    const refFunc = (dom) => {\n      if (dom) {\n        ref = dom;\n      }\n    };\n\n    class Example1 extends Component {\n      render() {\n        instance1 = this;\n        return <div id=\"example1\" />;\n      }\n    }\n\n    class Example2 extends Component {\n      render() {\n        instance2 = this;\n        return <div id=\"example2\" />;\n      }\n    }\n\n    class Example3 extends Component {\n      render() {\n        instance3 = this;\n        return (\n          <div id=\"example3\" ref={refFunc}>\n            <Example2 />\n            <Example1 />\n          </div>\n        );\n      }\n    }\n\n    it('simple findDOMNodes', () => {\n      render(<Example1 />, container);\n      expect(findDOMNode(instance1)).toBe(document.getElementById('example1'));\n      render(null, container);\n      expect(findDOMNode(instance1)).toBe(null);\n      render(<Example2 />, container);\n      expect(\n        findDOMNode(instance2) === document.getElementById('example2'),\n      ).toBe(true);\n      render(<Example1 />, container);\n      expect(\n        findDOMNode(instance1) === document.getElementById('example1'),\n      ).toBe(true);\n      render(<Example3 />, container);\n      expect(\n        findDOMNode(instance3) === document.getElementById('example3'),\n      ).toBe(true);\n      expect(\n        findDOMNode(instance2) === document.getElementById('example2'),\n      ).toBe(true);\n      expect(\n        findDOMNode(instance1) === document.getElementById('example1'),\n      ).toBe(true);\n      render(null, container);\n      expect(findDOMNode(instance1)).toBe(null);\n      expect(findDOMNode(instance2)).toBe(null);\n      expect(findDOMNode(instance3)).toBe(null);\n      expect(findDOMNode(ref) === ref).toBe(true);\n    });\n\n    it('Non existent ref should return null', () => {\n      expect(findDOMNode(null)).toBe(null);\n      expect(findDOMNode({})).toBe(null);\n    });\n\n    it('finds the first child when a component returns a fragment', () => {\n      class FragmentTester extends Component {\n        render() {\n          return [<div key=\"a\" />, <span key=\"b\" />];\n        }\n      }\n\n      let instance = null;\n      render(<FragmentTester ref={(ref) => (instance = ref)} />, container);\n\n      expect(container.childNodes.length).toBe(2);\n\n      const firstNode = findDOMNode(instance);\n      expect(firstNode).toBe(container.firstChild);\n      expect(firstNode.tagName).toBe('DIV');\n    });\n\n    it('finds the first child even when fragment is nested', () => {\n      class Wrapper extends Component {\n        render() {\n          return this.props.children;\n        }\n      }\n\n      class FragmentTester extends Component {\n        render() {\n          return [\n            <Wrapper key=\"a\">\n              <div />\n            </Wrapper>,\n            <span key=\"b\" />,\n          ];\n        }\n      }\n\n      let instance = null;\n      render(<FragmentTester ref={(ref) => (instance = ref)} />, container);\n\n      expect(container.childNodes.length).toBe(2);\n\n      const firstNode = findDOMNode(instance);\n      expect(firstNode).toBe(container.firstChild);\n      expect(firstNode.tagName).toBe('DIV');\n    });\n\n    it('finds the first child even when first child renders null', () => {\n      class NullComponent extends Component {\n        render() {\n          return null;\n        }\n      }\n\n      class FragmentTester extends Component {\n        render() {\n          return [<NullComponent key=\"a\" />, <div key=\"b\" />, <span key=\"c\" />];\n        }\n      }\n\n      let instance = null;\n      ReactDOM.render(\n        <FragmentTester ref={(ref) => (instance = ref)} />,\n        container,\n      );\n\n      expect(container.childNodes.length).toBe(3);\n\n      const firstNode = findDOMNode(instance);\n      expect(firstNode).toBe(container.firstChild);\n      // expect(firstNode.tagName).toBe('DIV'); This is components placeholder\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/isValidElement.spec.jsx",
    "content": "import { createElement } from 'inferno-create-element';\nimport { isValidElement } from 'inferno-shared';\nimport { Component } from 'inferno';\nimport { cloneVNode } from 'inferno-clone-vnode';\nimport { h } from 'inferno-hyperscript';\n\ndescribe('isValidElement', () => {\n  it('Should not work with non-object', () => {\n    expect(isValidElement(33)).toBe(false);\n    expect(isValidElement(false)).toBe(false);\n    expect(isValidElement(true)).toBe(false);\n    expect(isValidElement('some text')).toBe(false);\n    expect(isValidElement(0)).toBe(false);\n    expect(isValidElement(undefined)).toBe(false);\n  });\n\n  it('Should not work with invalid object', () => {\n    expect(isValidElement(null)).toBe(false);\n    expect(isValidElement({})).toBe(false);\n    expect(isValidElement({ dom: 'fake data' })).toBe(false);\n  });\n\n  it('Should not work with a number', () => {\n    expect(isValidElement(33)).toBe(false);\n  });\n\n  it('Should work with createElement (element)', () => {\n    const el = createElement('div', null, 'Do a thing');\n    expect(isValidElement(el)).toBe(true);\n  });\n\n  it('Should work with createElement (stateless component)', () => {\n    const el = createElement('div', null, 'Do a thing');\n    const Comp = () => el;\n    const comp = createElement(Comp);\n    expect(isValidElement(comp)).toBe(true);\n  });\n\n  it('Should work with createElement (stateful component)', () => {\n    class Comp extends Component {\n      render() {\n        return createElement('div', null, 'Do a thing');\n      }\n    }\n    const comp = createElement(Comp);\n    expect(isValidElement(comp)).toBe(true);\n  });\n\n  it('Should work with JSX', () => {\n    const node = <div>Hello world</div>;\n    expect(isValidElement(node)).toBe(true);\n  });\n\n  it('Should work with cloneVNode', () => {\n    const node = <div>Hello world</div>;\n    const clonedNode = cloneVNode(node, null, 'Hello world 2!');\n    expect(isValidElement(clonedNode)).toBe(true);\n  });\n\n  it('Should work with hyperscript (element)', () => {\n    const el = h('div', 'Do a thing');\n    expect(isValidElement(el)).toBe(true);\n  });\n\n  it('Should work with hyperscript (stateless component)', () => {\n    const el = h('div', 'Do a thing');\n    const Comp = () => el;\n    const comp = h(Comp);\n    expect(isValidElement(comp)).toBe(true);\n  });\n\n  it('Should work with hyperscript (stateful component)', () => {\n    class Comp extends Component {\n      render() {\n        return h('div', 'Do a thing');\n      }\n    }\n    const comp = h(Comp);\n    expect(isValidElement(comp)).toBe(true);\n  });\n\n  it('Should not work with a stateless component (using createElement)', () => {\n    const el = createElement('div', null, 'Do a thing');\n    const Comp = () => el;\n    expect(isValidElement(Comp)).toBe(false);\n  });\n\n  it('Should not work with a stateless component (using hyperscript)', () => {\n    const el = h('div', 'Do a thing');\n    const Comp = () => el;\n    expect(isValidElement(Comp)).toBe(false);\n  });\n\n  it('Should not work with a stateful component (using createElement)', () => {\n    class Comp extends Component {\n      render() {\n        return createElement('div', null, 'Do a thing');\n      }\n    }\n    expect(isValidElement(Comp)).toBe(false);\n  });\n\n  it('Should not work with a stateful component (using hyperscript)', () => {\n    class Comp extends Component {\n      render() {\n        return h('div', 'Do a thing');\n      }\n    }\n    expect(isValidElement(Comp)).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/lifecycle.spec.jsx",
    "content": "import { Component, createElement, render } from 'inferno-compat';\n\ndescribe('Inferno-compat LifeCycle', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('Order of Es6 Lifecycle with string refs and refs', () => {\n    it('Should go as per React', () => {\n      // We spy console log to verify order of callbacks\n      // React implementation: https://jsfiddle.net/art58y3L/\n      spyOn(console, 'log');\n\n      class Hello2 extends Component {\n        componentWillMount() {\n          console.log('Will mount sub');\n        }\n\n        componentDidMount() {\n          console.log('Did mount sub');\n        }\n\n        componentWillUpdate() {\n          console.log('Will update sub');\n        }\n\n        componentDidUpdate() {\n          console.log('Did update sub');\n        }\n\n        render() {\n          return createElement(\n            'div',\n            {\n              key: 'S1',\n              id: 'S1',\n              ref: (el) => {\n                console.log('S1' + (el ? el.id : null));\n              },\n            },\n            [\n              createElement('div', { key: 'ee' }),\n              createElement('div', {\n                key: 'S2b',\n                id: 'S2b',\n                ref: (el) => {\n                  console.log('S2b' + (el ? el.id : null));\n                },\n              }),\n            ],\n          );\n        }\n      }\n\n      class Hello extends Component {\n        componentWillMount() {\n          console.log('Will mount');\n        }\n\n        componentDidMount() {\n          console.log('Did mount');\n        }\n\n        componentWillUpdate() {\n          console.log('Will update');\n        }\n\n        componentDidUpdate() {\n          console.log('Did update');\n        }\n\n        render() {\n          return createElement(\n            'div',\n            {\n              key: '1',\n              id: '1',\n              ref: (el) => {\n                console.log('1' + (el ? el.id : null));\n              },\n            },\n            [\n              createElement(\n                'div',\n                {\n                  key: '2a',\n                  id: '2a',\n                  ref: (el) => {\n                    console.log('2a' + (el ? el.id : null));\n                  },\n                },\n                [\n                  createElement(Hello2, { key: 'Hello2' }),\n                  createElement('div', { key: 'empt' }, [\n                    createElement('div', {\n                      key: '4a',\n                      id: '4a',\n                      ref: (el) => {\n                        console.log('4a' + (el ? el.id : null));\n                      },\n                    }),\n                    createElement('div', {\n                      key: '4b',\n                      id: '4b',\n                      ref: (el) => {\n                        console.log('4b' + (el ? el.id : null));\n                      },\n                    }),\n                  ]),\n                  createElement('div', {\n                    key: '3b',\n                    id: '3b',\n                    ref: (el) => {\n                      console.log('3b' + (el ? el.id : null));\n                    },\n                  }),\n                ],\n              ),\n              createElement(\n                'div',\n                {\n                  key: '2b',\n                  id: '2b',\n                  ref: (el) => {\n                    console.log('2b' + (el ? el.id : null));\n                  },\n                },\n                null,\n              ),\n            ],\n          );\n        }\n      }\n\n      render(createElement(Hello, { name: 'Inferno' }), container);\n\n      console.log('UPDATE');\n\n      render(createElement(Hello, { name: 'Better Lifecycle' }), container);\n\n      console.log('REMOVAL');\n\n      render(<div />, container);\n\n      expect(console.log).toHaveBeenCalledTimes(42);\n\n      /*\n      React oder is:, Inferno will differenciate in string refs because they are handled same way as callback refs\n      Will mount\n      Will mount sub\n      S2bS2b\n      S1S1\n      Didountsub\n      4a4a\n      4b4b\n      3b3b\n      2a2a\n      2b2b\n      11\n      Didmount\n      UPDATE\n      Willupdate\n      Willupdatesub\n      S2bnull\n      S1null\n      4anull\n      4bnull\n      3bnull\n      2anull\n      2bnull\n      1null\n      S2bS2b\n      S1S1\n      Didupdatesub\n      4a4a\n      4b4b\n      3b3b\n      2a2a\n      2b2b\n      11\n      Didupdate\n      REMOVAL\n      1null\n      2anull\n      S1null\n      S2bnull\n      4anull\n      4bnull\n      3bnull\n      2bnull\n       */\n\n      // // mount\n      let i = -1;\n\n      const calls = console.log.calls;\n\n      expect(calls.argsFor(++i)).toEqual(['Will mount']);\n      expect(calls.argsFor(++i)).toEqual(['Will mount sub']);\n      expect(calls.argsFor(++i)).toEqual(['S2bS2b']);\n      expect(calls.argsFor(++i)).toEqual(['S1S1']);\n      expect(calls.argsFor(++i)).toEqual(['Did mount sub']);\n      expect(calls.argsFor(++i)).toEqual(['4a4a']);\n      expect(calls.argsFor(++i)).toEqual(['4b4b']);\n      expect(calls.argsFor(++i)).toEqual(['3b3b']);\n      expect(calls.argsFor(++i)).toEqual(['2a2a']);\n      expect(calls.argsFor(++i)).toEqual(['2b2b']);\n      expect(calls.argsFor(++i)).toEqual(['11']);\n      expect(calls.argsFor(++i)).toEqual(['Did mount']);\n\n      // update\n      // expect(calls.argsFor(++i)).toEqual(['UPDATE']);\n      // expect(calls.argsFor(++i)).toEqual(['Will update']);\n      // expect(calls.argsFor(++i)).toEqual(['Will update sub']);\n      // expect(calls.argsFor(++i)).toEqual(['S2bnull']);\n      // expect(calls.argsFor(++i)).toEqual(['S1null']);\n      // expect(calls.argsFor(++i)).toEqual(['4anull']);\n      // expect(calls.argsFor(++i)).toEqual(['4bnull']);\n      // expect(calls.argsFor(++i)).toEqual(['3bnull']);\n      // expect(calls.argsFor(++i)).toEqual(['2anull']);\n      // expect(calls.argsFor(++i)).toEqual(['2bnull']);\n      // expect(calls.argsFor(++i)).toEqual(['1null']);\n      // expect(calls.argsFor(++i)).toEqual(['S2bS2b']);\n      // expect(calls.argsFor(++i)).toEqual(['S1S1']);\n      // expect(calls.argsFor(++i)).toEqual(['Did update sub']);\n      // expect(calls.argsFor(++i)).toEqual(['4a4a']);\n      // expect(calls.argsFor(++i)).toEqual(['4b4b']);\n      // expect(calls.argsFor(++i)).toEqual(['3b3b']);\n      // expect(calls.argsFor(++i)).toEqual(['2a2a']);\n      // expect(calls.argsFor(++i)).toEqual(['2b2b']);\n      // expect(calls.argsFor(++i)).toEqual(['11']);\n\n      // unmount\n      // expect(calls.argsFor(++i)).toEqual(['REMOVAL']);\n      // expect(calls.argsFor(++i)).toEqual(['1null']);\n      // expect(calls.argsFor(++i)).toEqual(['2anull']);\n      // expect(calls.argsFor(++i)).toEqual(['S1null']);\n      // expect(calls.argsFor(++i)).toEqual(['S2bnull']);\n      // expect(calls.argsFor(++i)).toEqual(['4anull']);\n      // expect(calls.argsFor(++i)).toEqual(['4bnull']);\n      // expect(calls.argsFor(++i)).toEqual(['3bnull']);\n      // expect(calls.argsFor(++i)).toEqual(['2bnull']);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/misc.spec.jsx",
    "content": "import React, {\n  Children,\n  cloneElement,\n  Component,\n  createElement,\n  hydrate,\n  PropTypes,\n  render,\n  unstable_renderSubtreeIntoContainer,\n} from 'inferno-compat';\n\ndescribe('MISC', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('PropTypes', () => {\n    it('PropTypes should exists in inferno-compat', () => {\n      expect(typeof PropTypes).toBe('object');\n      expect(PropTypes.any()).toBeTruthy();\n      expect(typeof PropTypes.any().isRequired).toBe('function');\n      expect(PropTypes.any().isRequired()).toBeUndefined();\n    });\n\n    it('checkPropTypes should return null', () => {\n      expect(PropTypes.checkPropTypes()).toBeNull();\n    });\n  });\n\n  describe('React Synthetic event simulation', () => {\n    it('should have isPropagationStopped and isDefaultPrevented defined in Event prototype', () => {\n      const spyObj = {\n        foo: (event) => {\n          expect(event.isDefaultPrevented()).toBe(false);\n          expect(event.isPropagationStopped()).toBe(false);\n\n          event.preventDefault();\n          expect(event.isDefaultPrevented()).toBe(true);\n\n          event.stopPropagation();\n          expect(event.isPropagationStopped()).toBe(true);\n        },\n      };\n      spyOn(spyObj, 'foo').and.callThrough();\n\n      render(<div onClick={spyObj.foo} />, container);\n\n      container.firstChild.click();\n\n      expect(spyObj.foo).toHaveBeenCalledTimes(1);\n    });\n  });\n\n  describe('Children Only', () => {\n    it('Should return first of array', () => {\n      const divOne = <div />;\n      const children = [divOne];\n\n      expect(Children.only(children)).toBe(divOne);\n    });\n\n    it('Should two if children length is not one', () => {\n      const divOne = <div />;\n      const children = [divOne, 'two', 3];\n\n      expect(() => Children.only(children)).toThrow();\n    });\n  });\n\n  describe('Children toArray', () => {\n    it('Should return child in array', () => {\n      const divOne = <div />;\n\n      expect(Children.toArray(divOne)).toEqual([divOne]);\n    });\n\n    it('Should return array if its already array', () => {\n      const children = [<div />];\n\n      expect(Children.toArray(children)).toEqual(children);\n    });\n\n    it('Should return empty array if its null/undef', () => {\n      const children = null;\n\n      expect(Children.toArray(children)).toEqual([]);\n    });\n  });\n\n  describe('render()', () => {\n    it('should be exported', () => {\n      expect(React.render).toBe(render);\n    });\n\n    it('should replace isomorphic content', () => {\n      const ce = (type) => document.createElement(type);\n      const Text = (text) => document.createTextNode(text);\n      const root = ce('div');\n      const initialChild = ce('div');\n      initialChild.appendChild(Text('initial content'));\n      root.appendChild(initialChild);\n\n      hydrate(<div>dynamic content</div>, root);\n      expect(root.textContent).toEqual('dynamic content');\n    });\n\n    it('hydrate should remove extra elements', () => {\n      const ce = (type) => document.createElement(type);\n      const Text = (text) => document.createTextNode(text);\n      const root = ce('div');\n\n      const c1 = ce('div');\n      c1.appendChild(Text('isomorphic content'));\n      root.appendChild(c1);\n\n      const c2 = ce('div');\n      c2.appendChild(Text('extra content'));\n      root.appendChild(c2);\n\n      hydrate(<div>dynamic content</div>, root);\n      expect(root.textContent).toEqual('dynamic content');\n    });\n\n    it('should remove text nodes', () => {\n      const ce = (type) => document.createElement(type);\n      const Text = (text) => document.createTextNode(text);\n      const root = ce('div');\n\n      root.appendChild(Text('Text Content in the root'));\n      root.appendChild(Text('More Text Content'));\n\n      hydrate(<div>dynamic content</div>, root);\n      expect(root.textContent).toEqual('dynamic content');\n    });\n\n    it('should support defaultValue', () => {\n      const div2 = document.createElement('div');\n      (document.body || document.documentElement).appendChild(div2);\n      render(<input defaultValue=\"foo\" />, div2);\n      expect(div2.firstElementChild.value).toBe('foo');\n\n      render(null, div2);\n      document.body.removeChild(div2);\n    });\n  });\n\n  describe('createElement()', () => {\n    it('should be exported', () => {\n      expect(React.createElement).toBe(createElement);\n    });\n  });\n\n  describe('Component', () => {\n    it('should be exported', () => {\n      expect(React.Component).toEqual(Component);\n    });\n  });\n\n  describe('cloneElement', () => {\n    it('should clone elements', () => {\n      const element = (\n        <foo a=\"b\" c=\"d\">\n          a<span>b</span>\n        </foo>\n      );\n      expect(JSON.stringify(cloneElement(element).children)).toEqual(\n        JSON.stringify(element.children),\n      );\n    });\n\n    it('should support props.children', () => {\n      const element = <foo children={<span>b</span>} />;\n      const clone = cloneElement(element);\n\n      expect(cloneElement(clone).props.children).toEqual(\n        element.props.children,\n      );\n    });\n\n    it('children take precedence over props.children', () => {\n      const element = (\n        <foo children={<span>c</span>}>\n          <div>b</div>\n        </foo>\n      );\n      const clone = cloneElement(element);\n\n      expect(clone.children.children).toEqual('b');\n    });\n\n    it('should support children in prop argument', () => {\n      const element = <foo />;\n      const children = [<span>b</span>];\n      const clone = cloneElement(element, { children });\n      expect(JSON.stringify(clone.children)).toEqual(JSON.stringify(children));\n    });\n\n    it('children argument takes precedence over props.children', () => {\n      const element = <foo />;\n      const childrenA = [<span>b</span>];\n      const childrenB = [<div>c</div>];\n      const clone = cloneElement(element, { children: childrenA }, childrenB);\n      expect(JSON.stringify(clone.children)).toEqual(JSON.stringify(childrenB));\n    });\n\n    it('children argument takes precedence over props.children even if falsey', () => {\n      const element = <foo />;\n      const childrenA = [<span>b</span>];\n      const clone = cloneElement(element, { children: childrenA }, undefined);\n      expect(clone.children).toEqual(null);\n    });\n  });\n\n  describe('unstable_renderSubtreeIntoContainer', () => {\n    class Inner extends Component {\n      render() {\n        return null;\n      }\n\n      getNode() {\n        return 'inner';\n      }\n    }\n\n    it('should export instance', () => {\n      class App extends Component {\n        render() {\n          return null;\n        }\n\n        componentDidMount() {\n          this.renderInner();\n        }\n\n        renderInner() {\n          const wrapper = document.createElement('div');\n          this.inner = unstable_renderSubtreeIntoContainer(\n            this,\n            <Inner />,\n            wrapper,\n          );\n        }\n      }\n      const root = document.createElement('div');\n      const app = render(<App />, root);\n      expect(typeof app.inner.getNode === 'function').toEqual(true);\n    });\n\n    it('should there must be a context in callback', () => {\n      class App extends Component {\n        render() {\n          return null;\n        }\n\n        componentDidMount() {\n          this.renderInner();\n        }\n\n        renderInner() {\n          const wrapper = document.createElement('div');\n          const self = this;\n          unstable_renderSubtreeIntoContainer(\n            this,\n            <Inner />,\n            wrapper,\n            function () {\n              self.inner = this;\n            },\n          );\n        }\n      }\n      const root = document.createElement('div');\n      const app = render(<App />, root);\n      expect(typeof app.inner.getNode === 'function').toEqual(true);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/onlyChild.spec.jsx",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @emails react-core\n */\n\nimport React from 'inferno-compat';\n\ndescribe('onlyChild', function () {\n  let onlyChild;\n  class WrapComponent extends React.Component {\n    render() {\n      return (\n        <div>{onlyChild(this.props.children, this.props.mapFn, this)}</div>\n      );\n    }\n  }\n\n  beforeEach(function () {\n    onlyChild = React.Children.only;\n  });\n\n  it('should fail when passed two children', function () {\n    expect(function () {\n      const instance = (\n        <WrapComponent>\n          <div />\n          <span />\n        </WrapComponent>\n      );\n      onlyChild(instance.props.children);\n    }).toThrow();\n  });\n\n  it('should fail when passed nully values', function () {\n    expect(function () {\n      const instance = <WrapComponent>{null}</WrapComponent>;\n      onlyChild(instance.props.children);\n    }).toThrow();\n\n    expect(function () {\n      const instance = <WrapComponent>{undefined}</WrapComponent>;\n      onlyChild(instance.props.children);\n    }).toThrow();\n  });\n\n  it('should not fail when passed interpolated single child', function () {\n    expect(function () {\n      const instance = <WrapComponent>{<span />}</WrapComponent>;\n      onlyChild(instance.props.children);\n    }).not.toThrow();\n  });\n\n  it('should return the only child', function () {\n    expect(function () {\n      const instance = (\n        <WrapComponent>\n          <span />\n        </WrapComponent>\n      );\n      onlyChild(instance.props.children);\n    }).not.toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/styles.spec.jsx",
    "content": "import { render } from 'inferno-compat';\n\ndescribe('Compat - styles', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should be possible to use camelCase styles when reactStyles support is on', () => {\n    render(<div style={{ backgroundColor: 'red' }}>Test</div>, container);\n\n    expect(container.innerHTML).toBe(\n      `<div style=\"background-color: red;\">Test</div>`,\n    );\n  });\n\n  it('Should automatically add px suffix to whitelisted numeric style properties', () => {\n    render(<div style={{ width: 10, zIndex: 1 }}>foo</div>, container);\n\n    expect(container.innerHTML).toBe(\n      `<div style=\"width: 10px; z-index: 1;\">foo</div>`,\n    );\n  });\n\n  it('Should be possible to use hyphen case props too', () => {\n    render(\n      <div style={{ 'background-color': 'blue', 'z-index': 3 }}>foo</div>,\n      container,\n    );\n\n    expect(container.firstChild.style.backgroundColor).toBe('blue');\n    expect(container.firstChild.style.zIndex + '').toBe('3');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/svg.spec.jsx",
    "content": "import { createElement, render } from 'inferno-compat';\n\ndescribe('svg', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n  });\n\n  afterEach(function () {\n    render(null, container);\n  });\n\n  it('Should work with normal svg attributes', () => {\n    render(\n      createElement(\n        'svg',\n        {\n          height: '16',\n          width: '16',\n          viewBox: '0 0 1024 1024',\n        },\n        [\n          createElement('stop', {\n            offset: 0,\n            stopColor: 'white',\n            stopOpacity: 0.5,\n          }),\n        ],\n      ),\n      container,\n    );\n\n    expect(container.firstChild.getAttribute('viewBox')).toBe('0 0 1024 1024');\n    expect(container.firstChild.getAttribute('height')).toBe('16');\n    expect(container.firstChild.getAttribute('width')).toBe('16');\n    expect(container.firstChild.firstChild.tagName).toBe('stop');\n    expect(container.firstChild.firstChild.getAttribute('stop-color')).toBe(\n      'white',\n    );\n    expect(container.firstChild.firstChild.getAttribute('stop-opacity')).toBe(\n      '0.5',\n    );\n  });\n\n  it('Should work with namespace svg attributes', () => {\n    render(\n      createElement('svg', null, [\n        createElement('image', {\n          xlinkHref: 'http://i.imgur.com/w7GCRPb.png',\n        }),\n      ]),\n      container,\n    );\n\n    expect(container.firstChild.firstChild.tagName).toBe('image');\n    expect(container.firstChild.firstChild.getAttribute('xlink:href')).toBe(\n      'http://i.imgur.com/w7GCRPb.png',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/testutils.spec.jsx",
    "content": "import { createComponentVNode, createElement } from 'inferno-compat';\nimport * as TestUtils from 'inferno-test-utils';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\ndescribe('Inferno-compat: renderToSnapshot', () => {\n  it('should return a snapshot with className prop, multiple children', () => {\n    function TestComponent(props) {\n      return createElement('div', null, [\n        props.children,\n        createElement('span', null, '1'),\n      ]);\n    }\n\n    const snapshot = TestUtils.renderToSnapshot(\n      createComponentVNode(VNodeFlags.ComponentFunction, TestComponent, {\n        children: [\n          createComponentVNode(VNodeFlags.ComponentFunction, TestComponent, {\n            children: [\n              createElement('span', null, 'a'),\n              createElement('span', null, 'b'),\n            ],\n          }),\n          createElement('span', null, 'a'),\n          createElement('span', null, 'b'),\n        ],\n      }),\n    );\n\n    expect(JSON.stringify(snapshot)).toBe(\n      '{\"children\":[{\"children\":[{\"children\":[\"a\"],\"props\":{},\"type\":\"span\"},{\"children\":[\"b\"],\"props\":{},\"type\":\"span\"},{\"children\":[\"1\"],\"props\":{},\"type\":\"span\"}],\"props\":{},\"type\":\"div\"},{\"children\":[\"a\"],\"props\":{},\"type\":\"span\"},{\"children\":[\"b\"],\"props\":{},\"type\":\"span\"},{\"children\":[\"1\"],\"props\":{},\"type\":\"span\"}],\"props\":{},\"type\":\"div\"}',\n    );\n  });\n\n  it('should correctly handle null children', () => {\n    function TestComponent(props) {\n      return createElement('div', null, [\n        props.children,\n        createElement('span', null, '1'),\n      ]);\n    }\n\n    const snapshot = TestUtils.renderToSnapshot(\n      createComponentVNode(VNodeFlags.ComponentFunction, TestComponent, {\n        children: [\n          createComponentVNode(VNodeFlags.ComponentFunction, TestComponent, {\n            children: [null, undefined],\n          }),\n          createElement('span', null, 'a'),\n          createElement('span', null, 'b'),\n        ],\n      }),\n    );\n\n    expect(JSON.stringify(snapshot)).toBe(\n      '{\"children\":[{\"children\":[{\"children\":[\"1\"],\"props\":{},\"type\":\"span\"}],\"props\":{},\"type\":\"div\"},{\"children\":[\"a\"],\"props\":{},\"type\":\"span\"},{\"children\":[\"b\"],\"props\":{},\"type\":\"span\"},{\"children\":[\"1\"],\"props\":{},\"type\":\"span\"}],\"props\":{},\"type\":\"div\"}',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/__tests__/warnings.spec.jsx",
    "content": "import { render } from 'inferno-compat';\n\ndescribe('Warnings', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should warn if inferno-compat overrides existing onInput ( text ) handler', () => {\n    function myTest() {}\n    function anotherMethod() {}\n\n    const spy = spyOn(console, 'error');\n\n    render(\n      <input type=\"text\" onChange={anotherMethod} onInput={myTest} />,\n      container,\n    );\n\n    expect(spy.calls.count()).toBe(1);\n    expect(spy.calls.argsFor(0)).toEqual([\n      `Inferno-compat Warning! 'onInput' handler is reserved to support React like 'onChange' event flow.\nOriginal event handler 'function ${myTest.name}' will not be called.`,\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-compat/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n\nmodule.exports.default = module.exports;\n"
  },
  {
    "path": "packages/inferno-compat/lib/EventConstants.js",
    "content": "'use strict';\n\n/**\n * Types of raw signals from the browser caught at the top level.\n */\nvar topLevelTypes = {\n  topAbort: null,\n  topAnimationEnd: null,\n  topAnimationIteration: null,\n  topAnimationStart: null,\n  topBlur: null,\n  topCanPlay: null,\n  topCanPlayThrough: null,\n  topChange: null,\n  topClick: null,\n  topCompositionEnd: null,\n  topCompositionStart: null,\n  topCompositionUpdate: null,\n  topContextMenu: null,\n  topCopy: null,\n  topCut: null,\n  topDoubleClick: null,\n  topDrag: null,\n  topDragEnd: null,\n  topDragEnter: null,\n  topDragExit: null,\n  topDragLeave: null,\n  topDragOver: null,\n  topDragStart: null,\n  topDrop: null,\n  topDurationChange: null,\n  topEmptied: null,\n  topEncrypted: null,\n  topEnded: null,\n  topError: null,\n  topFocus: null,\n  topInput: null,\n  topInvalid: null,\n  topKeyDown: null,\n  topKeyPress: null,\n  topKeyUp: null,\n  topLoad: null,\n  topLoadedData: null,\n  topLoadedMetadata: null,\n  topLoadStart: null,\n  topMouseDown: null,\n  topMouseMove: null,\n  topMouseOut: null,\n  topMouseOver: null,\n  topMouseUp: null,\n  topPaste: null,\n  topPause: null,\n  topPlay: null,\n  topPlaying: null,\n  topProgress: null,\n  topRateChange: null,\n  topReset: null,\n  topScroll: null,\n  topSeeked: null,\n  topSeeking: null,\n  topSelectionChange: null,\n  topStalled: null,\n  topSubmit: null,\n  topSuspend: null,\n  topTextInput: null,\n  topTimeUpdate: null,\n  topTouchCancel: null,\n  topTouchEnd: null,\n  topTouchMove: null,\n  topTouchStart: null,\n  topTransitionEnd: null,\n  topVolumeChange: null,\n  topWaiting: null,\n  topWheel: null,\n};\n\nvar EventConstants = {\n  topLevelTypes: topLevelTypes,\n};\n\nexport default EventConstants;\n"
  },
  {
    "path": "packages/inferno-compat/lib/EventPluginHub.js",
    "content": "// so generates no-ops for now, we probably need to make this actually work?\nexport default {\n  injection: {\n    injectEventPluginsByName: function () {},\n  },\n};\n"
  },
  {
    "path": "packages/inferno-compat/lib/EventPluginUtils.js",
    "content": "function isEndish(topLevelType) {\n  return (\n    topLevelType === 'topMouseUp' ||\n    topLevelType === 'topTouchEnd' ||\n    topLevelType === 'topTouchCancel'\n  );\n}\n\nfunction isMoveish(topLevelType) {\n  return topLevelType === 'topMouseMove' || topLevelType === 'topTouchMove';\n}\nfunction isStartish(topLevelType) {\n  return topLevelType === 'topMouseDown' || topLevelType === 'topTouchStart';\n}\n\nexport default {\n  isEndish: isEndish,\n  isMoveish: isMoveish,\n  isStartish: isStartish,\n};\n"
  },
  {
    "path": "packages/inferno-compat/lib/EventPropagators.js",
    "content": "// so generates no-ops for now, we probably need to make this actually work?\nexport default {\n  accumulateTwoPhaseDispatches: function () {},\n};\n"
  },
  {
    "path": "packages/inferno-compat/lib/ReactCSSTransitionGroup.js",
    "content": "export * from 'rc-css-transition-group-modern';\n"
  },
  {
    "path": "packages/inferno-compat/lib/ReactFragment.js",
    "content": "import { createElement } from 'inferno-compat';\nimport { isValidElement } from 'inferno-shared';\n\nexport function create(obj) {\n  const children = [];\n  for (let key in obj) {\n    if (Object.prototype.hasOwnProperty.call(obj, key)) {\n      let child = [].concat(obj[key]);\n      for (var i = 0; i < child.length; i++) {\n        let c = child[i];\n        // if non-keyed, clone attrs and inject key\n        if (isValidElement(c) && !(c.props && c.props.key)) {\n          let a = {};\n          if (c.props) for (var j in c.props) a[j] = c.props[j];\n          a.key = key + '.' + i;\n          c = createElement(c.type, a, c.children);\n        }\n        if (c != null) children.push(c);\n      }\n    }\n  }\n  return children;\n}\n"
  },
  {
    "path": "packages/inferno-compat/lib/ReactMount.js",
    "content": "export { unmountComponentAtNode } from 'inferno-compat';\n"
  },
  {
    "path": "packages/inferno-compat/lib/ReactTransitionEvents.js",
    "content": "var supported, prefix;\n\nif (typeof document !== 'undefined' && document.createElement) {\n  var d = document.createElement('div');\n  for (var i in d.style) {\n    var m = i.match(/^(moz|webkit|ms|)(transition|animation)$/i);\n    if (m) supported = true;\n    if (m && m[1]) prefix = m[1];\n  }\n}\n\nfunction each(node, fn, listener, prefix) {\n  node[fn]((prefix || '') + 'TransitionEnd', listener);\n  node[fn]((prefix || '') + 'AnimationEnd', listener);\n  if (prefix) each(node, fn, listener);\n}\n\nexport default {\n  addEndEventListener(el, listener) {\n    if (supported) each(el, 'addEventListener', listener, prefix);\n    else setTimeout(listener, 0);\n  },\n  removeEndEventListener(el, listener) {\n    if (supported) each(el, 'removeEventListener', listener, prefix);\n  },\n};\n"
  },
  {
    "path": "packages/inferno-compat/lib/ReactTransitionGroup.js",
    "content": "export * from 'inferno-transition-group';\n"
  },
  {
    "path": "packages/inferno-compat/lib/SyntheticUIEvent.js",
    "content": "// so generates no-ops for now, we probably need to make this actually work?\nexport default {\n  SyntheticUIEvent: function () {\n    return {};\n  },\n};\n"
  },
  {
    "path": "packages/inferno-compat/lib/ViewportMetrics.js",
    "content": "'use strict';\n\nvar ViewportMetrics = {\n  currentScrollLeft: 0,\n\n  currentScrollTop: 0,\n\n  refreshScrollValues: function (scrollPosition) {\n    ViewportMetrics.currentScrollLeft = scrollPosition.x;\n    ViewportMetrics.currentScrollTop = scrollPosition.y;\n  },\n};\n\nexport default ViewportMetrics;\n"
  },
  {
    "path": "packages/inferno-compat/lib/shallowCompare.js",
    "content": "function shallowDiffers(a, b) {\n  let i;\n  for (i in a) if (!(i in b)) return true;\n  for (i in b) if (a[i] !== b[i]) return true;\n  return false;\n}\n\nexport default function (instance, nextProps, nextState) {\n  return (\n    shallowDiffers(instance.props, nextProps) ||\n    shallowDiffers(instance.state, nextState)\n  );\n}\n"
  },
  {
    "path": "packages/inferno-compat/package.json",
    "content": "{\n  \"name\": \"inferno-compat\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Provides a compatibility with React codebases\",\n  \"author\": {\n    \"name\": \"Dominic Gannaway\",\n    \"email\": \"dg@domgan.com\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-compat\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"files\": [\n    \"index.cjs\",\n    \"prop-types.js\",\n    \"lib\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"keywords\": [\n    \"babel\",\n    \"react\",\n    \"inferno\",\n    \"framework\",\n    \"interfaces\",\n    \"user interfaces\",\n    \"vdom\"\n  ],\n  \"dependencies\": {\n    \"inferno\": \"9.0.11\",\n    \"inferno-clone-vnode\": \"9.0.11\",\n    \"inferno-create-element\": \"9.0.11\",\n    \"inferno-extras\": \"9.0.11\",\n    \"inferno-hydrate\": \"9.0.11\"\n  },\n  \"devDependencies\": {\n    \"inferno-hyperscript\": \"9.0.11\",\n    \"inferno-shared\": \"9.0.11\",\n    \"inferno-test-utils\": \"9.0.11\",\n    \"inferno-vnode-flags\": \"9.0.11\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\",\n      \"inferno-vnode-flags\"\n    ],\n    \"moduleName\": \"Inferno\",\n    \"moduleGlobals\": {\n      \"inferno\": \"Inferno\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno-compat/src/InfernoCompatPropertyMap.ts",
    "content": "/**\n * This is a list of all SVG attributes that need special casing,\n * namespacing, or boolean value assignment.\n *\n * When adding attributes to this list, be sure to also add them to\n * the `possibleStandardNames` module to ensure casing and incorrect\n * name warnings.\n *\n * SVG Attributes List:\n * https://www.w3.org/TR/SVG/attindex.html\n * SMIL Spec:\n * https://www.w3.org/TR/smil\n */\nconst ATTRS = [\n  'accent-height',\n  'alignment-baseline',\n  'arabic-form',\n  'baseline-shift',\n  'cap-height',\n  'clip-path',\n  'clip-rule',\n  'color-interpolation',\n  'color-interpolation-filters',\n  'color-profile',\n  'color-rendering',\n  'dominant-baseline',\n  'enable-background',\n  'fill-opacity',\n  'fill-rule',\n  'flood-color',\n  'flood-opacity',\n  'font-family',\n  'font-size',\n  'font-size-adjust',\n  'font-stretch',\n  'font-style',\n  'font-constiant',\n  'font-weight',\n  'glyph-name',\n  'glyph-orientation-horizontal',\n  'glyph-orientation-vertical',\n  'horiz-adv-x',\n  'horiz-origin-x',\n  'image-rendering',\n  'letter-spacing',\n  'lighting-color',\n  'marker-end',\n  'marker-mid',\n  'marker-start',\n  'overline-position',\n  'overline-thickness',\n  'paint-order',\n  'panose-1',\n  'pointer-events',\n  'rendering-intent',\n  'shape-rendering',\n  'stop-color',\n  'stop-opacity',\n  'strikethrough-position',\n  'strikethrough-thickness',\n  'stroke-dasharray',\n  'stroke-dashoffset',\n  'stroke-linecap',\n  'stroke-linejoin',\n  'stroke-miterlimit',\n  'stroke-opacity',\n  'stroke-width',\n  'text-anchor',\n  'text-decoration',\n  'text-rendering',\n  'underline-position',\n  'underline-thickness',\n  'unicode-bidi',\n  'unicode-range',\n  'units-per-em',\n  'v-alphabetic',\n  'v-hanging',\n  'v-ideographic',\n  'v-mathematical',\n  'vector-effect',\n  'vert-adv-y',\n  'vert-origin-x',\n  'vert-origin-y',\n  'word-spacing',\n  'writing-mode',\n  'x-height',\n  'xlink:actuate',\n  'xlink:arcrole',\n  'xlink:href',\n  'xlink:role',\n  'xlink:show',\n  'xlink:title',\n  'xlink:type',\n  'xml:base',\n  'xmlns:xlink',\n  'xml:lang',\n  'xml:space',\n];\n\nexport const InfernoCompatPropertyMap = {\n  htmlFor: 'for',\n  onDoubleClick: 'onDblClick',\n};\n\nconst CAMELIZE = /[-:]([a-z])/g;\nfunction capitalize(token: string): string {\n  return token[1].toUpperCase();\n}\n\nfor (const original of ATTRS) {\n  const reactName = original.replace(CAMELIZE, capitalize);\n\n  InfernoCompatPropertyMap[reactName] = original;\n}\n"
  },
  {
    "path": "packages/inferno-compat/src/PropTypes.ts",
    "content": "/**\n * @module Inferno-Compat\n */\n/**\n * Inlined PropTypes, there is propType checking ATM.\n */\n\nfunction proptype() {}\n(proptype as any).isRequired = proptype;\n\nfunction getProptype(): Function {\n  return proptype;\n}\n\nconst PropTypes = {\n  any: getProptype,\n  array: proptype,\n  arrayOf: getProptype,\n  bool: proptype,\n  checkPropTypes: () => null,\n  element: getProptype,\n  func: proptype,\n  instanceOf: getProptype,\n  node: getProptype,\n  number: proptype,\n  object: proptype,\n  objectOf: getProptype,\n  oneOf: getProptype,\n  oneOfType: getProptype,\n  shape: getProptype,\n  string: proptype,\n  symbol: proptype,\n};\n\nexport default PropTypes;\n"
  },
  {
    "path": "packages/inferno-compat/src/index.ts",
    "content": "import {\n  renderInternal,\n  _CI,\n  _HI,\n  _M,\n  _MCCC,\n  _ME,\n  _MFCC,\n  _MP,\n  _MR,\n  Component,\n  createComponentVNode,\n  createFragment,\n  createPortal,\n  createRef,\n  createRenderer,\n  createTextVNode,\n  createVNode,\n  directClone,\n  EMPTY_OBJ,\n  findDOMFromVNode,\n  forwardRef,\n  Fragment,\n  getFlagsForElementVnode,\n  type InfernoNode,\n  linkEvent,\n  normalizeProps,\n  options,\n  rerender,\n  type VNode,\n} from 'inferno';\nimport { hydrate } from 'inferno-hydrate';\nimport { cloneVNode } from 'inferno-clone-vnode';\nimport { createElement } from 'inferno-create-element';\nimport {\n  isArray,\n  isFunction,\n  isInvalid,\n  isNull,\n  isNullOrUndef,\n  isNumber,\n  isString,\n  warning,\n} from 'inferno-shared';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { isValidElement } from 'inferno-shared';\nimport PropTypes from './PropTypes';\nimport { InfernoCompatPropertyMap } from './InfernoCompatPropertyMap';\nimport { findDOMNode } from 'inferno-extras';\nimport { getNumberStyleValue, hyphenCase } from './reactstyles';\n\nexport type { ComponentType, Inferno, Refs, VNode } from 'inferno';\n\ndeclare global {\n  interface Event {\n    persist: Function;\n  }\n}\n\noptions.reactStyles = true;\n\nfunction unmountComponentAtNode(\n  container: Element | SVGAElement | DocumentFragment,\n): boolean {\n  renderInternal(null, container, null, {});\n  return true;\n}\n\nexport type IterateChildrenFn = (\n  value: InfernoNode | any,\n  index: number,\n  array: any[],\n) => any;\n\nfunction flatten(arr, result): unknown[] {\n  for (let i = 0, len = arr.length; i < len; ++i) {\n    const value = arr[i];\n    if (isArray(value)) {\n      flatten(value, result);\n    } else {\n      result.push(value);\n    }\n  }\n  return result;\n}\n\nconst ARR = [];\n\nconst Children = {\n  map(children: any[], fn: IterateChildrenFn, ctx: any): any[] {\n    if (isNullOrUndef(children)) {\n      return children;\n    }\n    children = Children.toArray(children);\n    if (ctx) {\n      fn = fn.bind(ctx);\n    }\n    return children.map(fn);\n  },\n  forEach(children: any[], fn: IterateChildrenFn, ctx?: any): void {\n    if (isNullOrUndef(children)) {\n      return;\n    }\n    children = Children.toArray(children);\n    if (ctx) {\n      fn = fn.bind(ctx);\n    }\n    for (let i = 0, len = children.length; i < len; ++i) {\n      const child = isInvalid(children[i]) ? null : children[i];\n\n      fn(child, i, children);\n    }\n  },\n  count(children: any[]): number {\n    children = Children.toArray(children);\n    return children.length;\n  },\n  only(children: any[]): InfernoNode | any {\n    children = Children.toArray(children);\n    if (children.length !== 1) {\n      throw new Error('Children.only() expects only one child.');\n    }\n    return children[0];\n  },\n  toArray(children: any[]): any[] {\n    if (isNullOrUndef(children)) {\n      return [];\n    }\n    // We need to flatten arrays here,\n    // because React does it also and application level code might depend on that behavior\n    if (isArray(children)) {\n      const result = [];\n\n      flatten(children, result);\n\n      return result;\n    }\n    return ARR.concat(children);\n  },\n};\n\n(Component.prototype as any).isReactComponent = {};\n\nconst version = '15.4.2';\n\nconst validLineInputs = {\n  date: true,\n  'datetime-local': true,\n  email: true,\n  month: true,\n  number: true,\n  password: true,\n  search: true,\n  tel: true,\n  text: true,\n  time: true,\n  url: true,\n  week: true,\n};\n\nfunction normalizeGenericProps(props): void {\n  for (const prop in props) {\n    const mappedProp = InfernoCompatPropertyMap[prop];\n    if (mappedProp && props[prop] && mappedProp !== prop) {\n      props[mappedProp] = props[prop];\n      props[prop] = void 0;\n    }\n\n    if (options.reactStyles && prop === 'style') {\n      const styles = props.style;\n\n      if (styles && !isString(styles)) {\n        const newStyles = {};\n        for (const s in styles) {\n          const value = styles[s];\n          const hyphenStr = hyphenCase(s);\n\n          newStyles[hyphenStr] = isNumber(value)\n            ? getNumberStyleValue(hyphenStr, value)\n            : value;\n        }\n        props.style = newStyles;\n      }\n    }\n  }\n}\n\nfunction normalizeFormProps(name: string, props: any): void {\n  if (\n    (name === 'input' || name === 'textarea') &&\n    props.type !== 'radio' &&\n    props.onChange\n  ) {\n    const type = props.type?.toLowerCase();\n    let eventName;\n\n    if (!type || validLineInputs[type]) {\n      eventName = 'oninput';\n    }\n\n    if (eventName && !props[eventName]) {\n      if (process.env.NODE_ENV !== 'production') {\n        const existingMethod = props.oninput || props.onInput;\n\n        if (existingMethod) {\n          warning(\n            `Inferno-compat Warning! 'onInput' handler is reserved to support React like 'onChange' event flow.\nOriginal event handler 'function ${existingMethod.name}' will not be called.`,\n          );\n        }\n      }\n      props[eventName] = props.onChange;\n      props.onChange = void 0;\n    }\n  }\n}\n\n// we need to add persist() to Event (as React has it for synthetic events)\n// this is a hack, and we really shouldn't be modifying a global object this way,\n// but there isn't a performant way of doing this apart from trying to proxy\n// every prop event that starts with \"on\", i.e. onClick or onKeyPress\n// but in reality devs use onSomething for many things, not only for\n// input events\nif (typeof Event !== 'undefined') {\n  const eventProtoType = Event.prototype as any;\n\n  if (!eventProtoType.persist) {\n    eventProtoType.persist = function () {};\n  }\n}\n\nfunction iterableToArray(iterable): unknown[] {\n  let iterStep;\n  const tmpArr: any[] = [];\n  do {\n    iterStep = iterable.next();\n    tmpArr.push(iterStep.value);\n  } while (!iterStep.done);\n\n  return tmpArr;\n}\n\nconst g: any = typeof window === 'undefined' ? global : window;\nconst hasSymbolSupport = typeof g.Symbol !== 'undefined';\nconst symbolIterator = hasSymbolSupport ? g.Symbol.iterator : '';\nconst oldCreateVNode = options.createVNode;\n\noptions.createVNode = (vNode: VNode) => {\n  const children = vNode.children as any;\n  let props: any = vNode.props;\n\n  if (isNullOrUndef(props)) {\n    props = vNode.props = {};\n  }\n\n  // React supports iterable children, in addition to Array-like\n  if (\n    hasSymbolSupport &&\n    !isNull(children) &&\n    typeof children === 'object' &&\n    !isArray(children) &&\n    isFunction(children[symbolIterator])\n  ) {\n    vNode.children = iterableToArray(children[symbolIterator]());\n  }\n\n  if (!isNullOrUndef(children) && isNullOrUndef(props.children)) {\n    props.children = children;\n  }\n  if (vNode.flags & VNodeFlags.Component) {\n    if (isString(vNode.type)) {\n      vNode.flags = getFlagsForElementVnode(vNode.type);\n      if (props) {\n        normalizeProps(vNode);\n      }\n    }\n  }\n\n  const flags = vNode.flags;\n\n  if (flags & VNodeFlags.FormElement) {\n    normalizeFormProps(vNode.type, props);\n  }\n  if (flags & VNodeFlags.Element) {\n    if (vNode.className) {\n      props.className = vNode.className;\n    }\n    normalizeGenericProps(props);\n  }\n\n  if (oldCreateVNode) {\n    oldCreateVNode(vNode);\n  }\n};\n\n// Credit: preact-compat - https://github.com/developit/preact-compat :)\nfunction shallowDiffers(a, b): boolean {\n  let i;\n\n  for (i in a) {\n    if (!(i in b)) {\n      return true;\n    }\n  }\n\n  for (i in b) {\n    if (a[i] !== b[i]) {\n      return true;\n    }\n  }\n  return false;\n}\n\nabstract class PureComponent<P, S> extends Component<P, S> {\n  public shouldComponentUpdate(props, state): boolean {\n    return (\n      shallowDiffers(this.props, props) || shallowDiffers(this.state, state)\n    );\n  }\n}\n\ninterface ContextProps {\n  children?: InfernoNode;\n  context: any;\n}\n\nclass WrapperComponent<P, S> extends Component<P & ContextProps, S> {\n  public getChildContext(): (P & ContextProps)['context'] {\n    return this.props.context;\n  }\n\n  public render(props): InfernoNode {\n    return props.children;\n  }\n}\n\nfunction unstable_renderSubtreeIntoContainer(\n  parentComponent,\n  vNode,\n  container,\n  callback,\n): Component {\n  const wrapperVNode: VNode = createComponentVNode(\n    VNodeFlags.ComponentClass,\n    WrapperComponent,\n    {\n      children: vNode,\n      context: parentComponent.context,\n    },\n  );\n  render(wrapperVNode, container, null);\n  const component = vNode.children;\n\n  if (callback) {\n    // callback gets the component as context, no other argument.\n    callback.call(component);\n  }\n  return component;\n}\n\nfunction createFactory(type): (type) => VNode {\n  return createElement.bind(null, type);\n}\n\nfunction render(\n  rootInput,\n  container,\n  cb = null,\n  context = EMPTY_OBJ,\n): Component | undefined {\n  renderInternal(rootInput, container, cb, context);\n\n  const input = container.$V;\n\n  if (input && input.flags & VNodeFlags.Component) {\n    return input.children;\n  }\n\n  return void 0;\n}\n\n// Mask React global in browser enviornments when React is not used.\nif (\n  typeof window !== 'undefined' &&\n  typeof (window as any).React === 'undefined'\n) {\n  const exports = {\n    Children,\n    Component,\n    EMPTY_OBJ,\n    Fragment,\n    PropTypes,\n    PureComponent,\n    // Internal methods\n    _CI,\n    _HI,\n    _M,\n    _MCCC,\n    _ME,\n    _MFCC,\n    _MP,\n    _MR,\n    __render: renderInternal,\n    // Public methods\n    cloneElement: cloneVNode,\n    cloneVNode,\n    createComponentVNode,\n    createElement,\n    createFactory,\n    createFragment,\n    createPortal,\n    createRef,\n    createRenderer,\n    createTextVNode,\n    createVNode,\n    directClone,\n    findDOMFromVNode,\n    findDOMNode,\n    forwardRef,\n    getFlagsForElementVnode,\n    hydrate,\n    isValidElement,\n    linkEvent,\n    normalizeProps,\n    options,\n    render,\n    rerender,\n    unmountComponentAtNode,\n    unstable_renderSubtreeIntoContainer,\n    version,\n  };\n\n  (window as any).React = exports;\n  (window as any).ReactDOM = exports;\n}\n\nexport {\n  Children,\n  Component,\n  EMPTY_OBJ,\n  Fragment,\n  PropTypes,\n  PureComponent,\n  // Internal methods\n  _CI,\n  _HI,\n  _M,\n  _MCCC,\n  _ME,\n  _MFCC,\n  _MP,\n  _MR,\n  renderInternal,\n  // Public methods\n  cloneVNode as cloneElement,\n  cloneVNode,\n  createComponentVNode,\n  createElement,\n  createFactory,\n  createFragment,\n  createPortal,\n  createRef,\n  createRenderer,\n  createTextVNode,\n  createVNode,\n  directClone,\n  findDOMNode,\n  findDOMFromVNode,\n  forwardRef,\n  getFlagsForElementVnode,\n  hydrate,\n  isValidElement,\n  linkEvent,\n  normalizeProps,\n  options,\n  render,\n  rerender,\n  unmountComponentAtNode,\n  unstable_renderSubtreeIntoContainer,\n  version,\n};\n\nexport default {\n  Children,\n  Component,\n  EMPTY_OBJ,\n  Fragment,\n  PropTypes,\n  PureComponent,\n  // Internal methods\n  _CI,\n  _HI,\n  _M,\n  _MCCC,\n  _ME,\n  _MFCC,\n  _MP,\n  _MR,\n  __render: renderInternal,\n  // Public methods\n  cloneElement: cloneVNode,\n  cloneVNode,\n  createComponentVNode,\n  createElement,\n  createFactory,\n  createFragment,\n  createPortal,\n  createRef,\n  createRenderer,\n  createTextVNode,\n  createVNode,\n  directClone,\n  findDOMFromVNode,\n  findDOMNode,\n  forwardRef,\n  getFlagsForElementVnode,\n  hydrate,\n  isValidElement,\n  linkEvent,\n  normalizeProps,\n  options,\n  render,\n  rerender,\n  unmountComponentAtNode,\n  unstable_renderSubtreeIntoContainer,\n  version,\n};\n"
  },
  {
    "path": "packages/inferno-compat/src/reactstyles.ts",
    "content": "export function getNumberStyleValue(\n  style: string,\n  value: number,\n): string | number {\n  switch (style) {\n    case 'animation-iteration-count':\n    case 'border-image-outset':\n    case 'border-image-slice':\n    case 'border-image-width':\n    case 'box-flex':\n    case 'box-flex-group':\n    case 'box-ordinal-group':\n    case 'column-count':\n    case 'fill-opacity':\n    case 'flex':\n    case 'flex-grow':\n    case 'flex-negative':\n    case 'flex-order':\n    case 'flex-positive':\n    case 'flex-shrink':\n    case 'flood-opacity':\n    case 'font-weight':\n    case 'grid-column':\n    case 'grid-row':\n    case 'line-clamp':\n    case 'line-height':\n    case 'opacity':\n    case 'order':\n    case 'orphans':\n    case 'stop-opacity':\n    case 'stroke-dasharray':\n    case 'stroke-dashoffset':\n    case 'stroke-miterlimit':\n    case 'stroke-opacity':\n    case 'stroke-width':\n    case 'tab-size':\n    case 'widows':\n    case 'z-index':\n    case 'zoom':\n      return value;\n    default:\n      return value + 'px';\n  }\n}\n\nconst uppercasePattern = /[A-Z]/g;\n\nexport function hyphenCase(str: string): string {\n  return str.replace(uppercasePattern, '-$&').toLowerCase();\n}\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/callback.in.ctr.spec.tsx",
    "content": "import { Component, render, rerender } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('Callbacks in constructor', () => {\n  // https://github.com/infernojs/inferno/issues/1103\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('Github #1103', () => {\n    it('Should be possible to call callbacks from Component constructor - Use case 1', () => {\n      function InfoLi(props) {\n        const iddy = props.conf.key;\n        return (\n          <li>\n            <input\n              id={iddy}\n              type=\"checkbox\"\n              checked={props.checked}\n              onClick={props.onChange}\n            />\n            <label for={iddy}>{props.conf.label}</label>\n            <div>{props.children}</div>\n          </li>\n        );\n      }\n\n      interface ConfigsListProps {\n        onConfChanged: (arg: {\n          targetIndex: number;\n          newValue: unknown;\n        }) => void;\n        configs: unknown[];\n      }\n      interface ConfigsListState {\n        checks: boolean[];\n      }\n\n      class ConfigsList extends Component<ConfigsListProps, ConfigsListState> {\n        public state: ConfigsListState;\n\n        constructor(props) {\n          super(props);\n          this.state = {\n            checks: props.configs.map((conf) => Boolean(conf.value)),\n          };\n        }\n\n        public handleCheck(index, ifChecked) {\n          this.setState({\n            checks: this.state.checks.map((ch, i) =>\n              i === index ? ifChecked : ch,\n            ),\n          });\n        }\n\n        public handleNewValue(index, newValue) {\n          this.props.onConfChanged({\n            newValue,\n            targetIndex: index,\n          });\n        }\n\n        public render(props) {\n          return (\n            <ol>\n              {props.configs.map((conf, index) => {\n                const childElement = props.configToChild?.[conf.key];\n\n                const child =\n                  childElement &&\n                  this.state.checks[index] &&\n                  createElement(childElement, {\n                    ...props,\n                    conf,\n                    onNewValue: (newValue) => {\n                      this.handleNewValue(index, newValue);\n                    },\n                  });\n\n                return (\n                  <InfoLi\n                    conf={conf}\n                    checked={conf.value}\n                    onChange={(event) => {\n                      this.handleCheck(index, event.target.checked);\n                    }}\n                  >\n                    {child}\n                  </InfoLi>\n                );\n              })}\n            </ol>\n          );\n        }\n      }\n\n      interface ProxyEditorProps {\n        onNewValue: (arg: string) => void;\n      }\n\n      class ProxyEditor extends Component<ProxyEditorProps> {\n        constructor(props) {\n          super(props);\n\n          const oldValue = props.conf.value;\n          const newValue = oldValue || 'BA BA BA!';\n          if (!oldValue) {\n            this.props.onNewValue(newValue);\n          }\n        }\n\n        public render() {\n          return <div />;\n        }\n      }\n\n      interface MainState {\n        configs: Array<{\n          category: string;\n          key: string;\n          label: string;\n          value: boolean;\n        }>;\n      }\n\n      class Main extends Component<any, MainState> {\n        public state: MainState;\n\n        constructor(props) {\n          super(props);\n          this.state = {\n            configs: [\n              {\n                category: 'ownProxies',\n                key: 'customProxyStringRaw',\n                label: 'Use proxy? (click this)',\n                value: false,\n              },\n              {\n                category: 'ownProxies',\n                key: 'This one is needed for reproduction too!',\n                label: 'needed too',\n                value: false,\n              },\n            ],\n          };\n          this.handleModChange = this.handleModChange.bind(this);\n        }\n\n        public handleModChange({ targetIndex, newValue }) {\n          this.setState({\n            configs: this.state.configs.map((oldConf, index) =>\n              index !== targetIndex ? oldConf : { ...oldConf, value: newValue },\n            ),\n          });\n        }\n\n        public render(props) {\n          return createElement(ConfigsList, {\n            ...props,\n            configToChild: {\n              customProxyStringRaw: ProxyEditor,\n            },\n            configs: this.state.configs,\n            onConfChanged: this.handleModChange,\n          });\n        }\n      }\n\n      render(<Main />, container);\n\n      // Renders correctly\n      expect(container.innerHTML).toBe(\n        '<ol><li><input id=\"customProxyStringRaw\" type=\"checkbox\"><label for=\"customProxyStringRaw\">Use proxy? (click this)</label><div></div></li><li><input id=\"This one is needed for reproduction too!\" type=\"checkbox\"><label for=\"This one is needed for reproduction too!\">needed too</label><div></div></li></ol>',\n      );\n\n      let checkBoxes = container.querySelectorAll('input');\n\n      expect(checkBoxes.length).toBe(2);\n\n      expect(checkBoxes[0].checked).toBe(false);\n      expect(checkBoxes[1].checked).toBe(false);\n\n      checkBoxes[0].click(); // Click first checkbox\n      rerender();\n      checkBoxes = container.querySelectorAll('input');\n\n      expect(checkBoxes.length).toBe(2);\n\n      expect(checkBoxes[0].checked).toBe(true);\n      expect(checkBoxes[1].checked).toBe(false);\n\n      checkBoxes[0].click(); // Click first checkbox again\n      rerender();\n      checkBoxes = container.querySelectorAll('input');\n\n      expect(checkBoxes.length).toBe(2);\n\n      expect(checkBoxes[0].checked).toBe(true); // This is current expected behavior, same as React\n      expect(checkBoxes[1].checked).toBe(false);\n\n      checkBoxes[1].click(); // Click second checkbox, it should do nothing\n      rerender();\n      expect(checkBoxes[1].checked).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/children.spec.ts",
    "content": "import { render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('Children - (non-JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  const preDefined = [\n    {\n      name: 'undefined',\n      value: undefined,\n      expected: '',\n    },\n    {\n      name: 'null',\n      value: null,\n      expected: '',\n    },\n    {\n      name: 'one whitespace',\n      value: ' ',\n      expected: ' ',\n    },\n    {\n      name: 'whitespace to left',\n      value: 'a ',\n      expected: 'a ',\n    },\n    {\n      name: 'whitespace to right',\n      value: ' a',\n      expected: ' a',\n    },\n    {\n      name: 'should set children as empty string',\n      value: '',\n      expected: '',\n    },\n    {\n      name: 'should create a div with text, children property',\n      value: 'string',\n      expected: 'string',\n    },\n    {\n      name: '0',\n      value: 0,\n      expected: '0',\n    },\n    {\n      name: '0 (cast to string)',\n      value: '0',\n      expected: '0',\n    },\n    {\n      name: 'negative number',\n      value: -44444,\n      expected: '-44444',\n    },\n    {\n      name: 'negative number (cast to string)',\n      value: '-2344',\n      expected: '-2344',\n    },\n    {\n      name: 'NaN',\n      value: NaN,\n      expected: 'NaN',\n    },\n    {\n      name: 'empty array',\n      value: [],\n      expected: '',\n    },\n    {\n      name: 'simple math',\n      value: 123 - 33,\n      expected: '90',\n    },\n    {\n      name: 'advanced math',\n      value: 123 - 33 / 4 - 444 * 345,\n      expected: '-153065.25',\n    },\n    {\n      name: 'number array',\n      value: [1, 2, 3],\n      expected: '123',\n    },\n    {\n      name: 'number array (long array)',\n      value: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3],\n      expected: '123123123123',\n    },\n    {\n      name: 'number array (long mixed array)',\n      value: [1, '2', 3, '1', 2, 3, '1', 2, 3, 1, 2, '3'],\n      expected: '123123123123',\n    },\n    {\n      name: 'number array (long mixed array) and undefined and empty string',\n      value: [1, '2', '', '1', 2, 3, '1', 2, undefined, 1, 2, '3'],\n      expected: '1212312123',\n    },\n    {\n      name: 'number array (cast to string)',\n      value: ['1', '2', '3'],\n      expected: '123',\n    },\n    {\n      name: 'number array (cast to string) and various whitespaces',\n      value: [' 1 ', '2', '3  '],\n      expected: ' 1 23  ',\n    },\n    {\n      name: 'single undefined in an array',\n      value: [1, 2, undefined],\n      expected: '12',\n    },\n    {\n      name: 'undefined in the middle of an array',\n      value: [1, undefined, 3],\n      expected: '13',\n    },\n    {\n      name: 'dobule undefined in an array',\n      value: [1, undefined, undefined],\n      expected: '1',\n    },\n    {\n      name: 'triple undefined in an array',\n      value: [undefined, undefined, undefined],\n      expected: '',\n    },\n    {\n      name: 'triple empty string in an array',\n      value: ['', '', ''],\n      expected: '',\n    },\n    {\n      name: 'triple null in an array',\n      value: [null, null, null],\n      expected: '',\n    },\n    {\n      name: 'single null in an array',\n      value: [null],\n      expected: '',\n    },\n    {\n      name: 'single null in an array',\n      value: ['{}'],\n      expected: '{}',\n    },\n    {\n      name: 'mix of null and undefined in an array',\n      value: [null, undefined],\n      expected: '',\n    },\n    {\n      name: 'mix of null, undefined and empty string in an array',\n      value: [null, undefined, ''],\n      expected: '',\n    },\n    {\n      name: 'mix of null, undefined and a number in an array',\n      value: [null, undefined, 123],\n      expected: '123',\n    },\n    {\n      name: 'mix of null, undefined and a number in an array',\n      value: [null, undefined, 123, ' ', undefined, null, undefined],\n      expected: '123 ',\n    },\n    {\n      name: 'single empty string in an array',\n      value: [1, 2, ''],\n      expected: '12',\n    },\n    {\n      name: 'dobule empty string in an array',\n      value: [1, '', ''],\n      expected: '1',\n    },\n    {\n      name: 'triple empty string in an array',\n      value: ['', '', ''],\n      expected: '',\n    },\n    {\n      name: 'cast to string value, + single number in an array',\n      value: ['1', 2, 3],\n      expected: '123',\n    },\n    {\n      name: 'cast to strng value, + single number + a letter in an array',\n      value: ['1', 2, 'a'],\n      expected: '12a',\n    },\n    {\n      name: 'cast to strng value, + single number + a letter in an array',\n      value: ['1', null, 'a'],\n      expected: '1a',\n    },\n    {\n      name: 'cast to strng value, + single number + a letter in an array',\n      value: [undefined, null, 'a'],\n      expected: 'a',\n    },\n    {\n      name: 'cast to strng value, + single number + a letter in an array',\n      value: [undefined, null, 123, undefined, null],\n      expected: '123',\n    },\n  ];\n\n  for (const arg of preDefined) {\n    it('should set static children as ' + arg.name, () => {\n      render(createElement('div', null, arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n      render(createElement('div', null, arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n    });\n  }\n\n  for (const arg of preDefined) {\n    it('should set static deep children as ' + arg.name, () => {\n      const tmpl = () =>\n        createElement('div', null, createElement('span', null, arg.value));\n\n      render(tmpl(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.childNodes.length).toBe(1);\n      expect(container.firstChild.firstChild.textContent).toBe(arg.expected);\n      render(tmpl(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.childNodes.length).toBe(1);\n      expect(container.firstChild.firstChild.textContent).toBe(arg.expected);\n    });\n  }\n\n  for (const arg of preDefined) {\n    it('should set very deep static children as ' + arg.name, () => {\n      const tmpl = () =>\n        createElement(\n          'div',\n          null,\n          createElement(\n            'span',\n            null,\n            createElement('b', null, createElement('b', null, arg.value)),\n          ),\n        );\n\n      render(tmpl(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.childNodes.length).toBe(1);\n      expect(container.firstChild.firstChild.textContent).toBe(arg.expected);\n      render(tmpl(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.childNodes.length).toBe(1);\n      expect(container.firstChild.firstChild.textContent).toBe(arg.expected);\n    });\n  }\n\n  for (const arg of preDefined) {\n    const template = (child?) => createElement('div', null, child);\n\n    it('should set dynamic children as ' + arg.name, () => {\n      render(template(arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n      render(template(arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n      render(template(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe('');\n      render(template(arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n    });\n\n    it('should set dynamic children as ' + arg.name, () => {\n      render(template(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe('');\n      render(template(arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n    });\n\n    it('should set dynamic children as ' + arg.name, () => {\n      render(template(null), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe('');\n      render(template(arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n    });\n\n    it('should set dynamic children as ' + arg.name, () => {\n      render(template(arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n      render(template(null), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe('');\n    });\n\n    it('should set dynamic children as ' + arg.name, () => {\n      render(template(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe('');\n      render(template(undefined), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe('');\n    });\n\n    it('should set dynamic children as ' + arg.name, () => {\n      render(template(null), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe('');\n      render(template(null), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.textContent).toBe('');\n    });\n  }\n\n  for (const arg of preDefined) {\n    const template = (child?) =>\n      createElement('div', null, createElement('b', null, child));\n\n    it('should set deep dynamic children as ' + arg.name, () => {\n      render(template(arg.value), container);\n      expect(container.firstChild.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.firstChild.textContent).toBe(arg.expected);\n      render(template(arg.value), container);\n      expect(container.firstChild.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.firstChild.textContent).toBe(arg.expected);\n      render(template(null), container);\n      expect(container.firstChild.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.firstChild.textContent).toBe('');\n      render(template(undefined), container);\n      expect(container.firstChild.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.firstChild.textContent).toBe('');\n      render(template(), container);\n      expect(container.firstChild.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.firstChild.textContent).toBe('');\n    });\n  }\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/components.spec.ts",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('Components (non-JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    document.body.removeChild(container);\n  });\n\n  it('should pass', () => {\n    expect(true).toBeTruthy();\n  });\n\n  if (typeof global !== 'undefined' && !global.usingJSDOM) {\n    class BasicComponent1 extends Component<{ name: string; title: string }> {\n      render() {\n        const template = (name, title) =>\n          createElement(\n            'div',\n            {\n              className: 'basic',\n            },\n            createElement(\n              'span',\n              {\n                className: name,\n              },\n              'The title is ',\n              title,\n            ),\n          );\n        return template(this.props.name, this.props.title);\n      }\n    }\n\n    it('should recover from a basic error', () => {\n      const template = (Component, title) =>\n        createElement(\n          'div',\n          null,\n          createElement(Component, {\n            title,\n            name: 'basic-render',\n          }),\n        );\n\n      expect(() => {\n        render(template(null, 'abc'), container);\n      }).toThrow();\n\n      expect(() => {\n        render(template({}, 'abc'), container);\n      }).toThrow();\n\n      render(template(BasicComponent1, 'abc'), container);\n\n      expect(container.textContent).toBe('The title is abc');\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n        'basic',\n      );\n      expect(\n        container.firstChild.firstChild.firstChild.getAttribute('class'),\n      ).toBe('basic-render');\n      expect(container.firstChild.firstChild.tagName).toBe('DIV');\n      expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n      expect(container.firstChild.firstChild.firstChild.innerHTML).toBe(\n        'The title is abc',\n      );\n\n      expect(() => {\n        render(template({}, 'abc'), container);\n      }).toThrow();\n\n      expect(() => {\n        render(template(BasicComponent1, {}), container);\n      }).toThrow();\n\n      render(template(BasicComponent1, []), container);\n\n      expect(container.textContent).toBe('The title is ');\n\n      render(template(BasicComponent1, 'abcdef'), container);\n\n      expect(container.textContent).toBe('The title is abcdef');\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n        'basic',\n      );\n      expect(\n        container.firstChild.firstChild.firstChild.getAttribute('class'),\n      ).toBe('basic-render');\n      expect(container.firstChild.firstChild.tagName).toBe('DIV');\n      expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n      expect(container.firstChild.firstChild.firstChild.innerHTML).toBe(\n        'The title is abcdef',\n      );\n\n      render(template(BasicComponent1, null), container);\n\n      expect(container.textContent).toBe('The title is ');\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n        'basic',\n      );\n      expect(\n        container.firstChild.firstChild.firstChild.getAttribute('class'),\n      ).toBe('basic-render');\n      expect(container.firstChild.firstChild.tagName).toBe('DIV');\n      expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n      expect(container.firstChild.firstChild.firstChild.innerHTML).toBe(\n        'The title is ',\n      );\n\n      render(template(BasicComponent1, undefined), container);\n\n      expect(container.textContent).toBe('The title is ');\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n        'basic',\n      );\n      expect(\n        container.firstChild.firstChild.firstChild.getAttribute('class'),\n      ).toBe('basic-render');\n      expect(container.firstChild.firstChild.tagName).toBe('DIV');\n      expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n      expect(container.firstChild.firstChild.firstChild.innerHTML).toBe(\n        'The title is ',\n      );\n\n      render(template(BasicComponent1, '1234'), container);\n\n      expect(container.textContent).toBe('The title is 1234');\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n        'basic',\n      );\n      expect(\n        container.firstChild.firstChild.firstChild.getAttribute('class'),\n      ).toBe('basic-render');\n      expect(container.firstChild.firstChild.tagName).toBe('DIV');\n      expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n      expect(container.firstChild.firstChild.firstChild.innerHTML).toBe(\n        'The title is 1234',\n      );\n    });\n\n    class BasicComponent1b extends Component<{\n      isChecked: boolean;\n      title: string;\n    }> {\n      render() {\n        const template = (isChecked, title) =>\n          createElement(\n            'div',\n            {\n              className: 'basic',\n            },\n            createElement(\n              'label',\n              {},\n              createElement('input', {\n                type: 'checkbox',\n                checked: isChecked,\n              }),\n              'The title is ',\n              title,\n            ),\n          );\n        return template(this.props.isChecked, this.props.title);\n      }\n    }\n\n    it('should render a basic component with inputs', () => {\n      const template = (Component, title, isChecked) =>\n        createElement(\n          'div',\n          null,\n          createElement(Component, {\n            title,\n            isChecked,\n          }),\n        );\n\n      render(null, container);\n\n      render(template(BasicComponent1b, 'abc', true), container);\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n        'basic',\n      );\n      expect(\n        container.firstChild.firstChild.firstChild.firstChild.getAttribute(\n          'type',\n        ),\n      ).toBe('checkbox');\n      expect(container.firstChild.firstChild.tagName).toBe('DIV');\n      expect(container.firstChild.firstChild.firstChild.tagName).toBe('LABEL');\n      expect(container.firstChild.firstChild.firstChild.innerHTML).toBe(\n        '<input type=\"checkbox\">The title is abc',\n      );\n      expect(container.querySelector('input').checked).toBe(true);\n\n      render(null, container);\n      render(null, container);\n\n      render(template(BasicComponent1b, 'abc', null), container);\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n        'basic',\n      );\n      expect(\n        container.firstChild.firstChild.firstChild.firstChild.getAttribute(\n          'type',\n        ),\n      ).toBe('checkbox');\n      expect(container.firstChild.firstChild.tagName).toBe('DIV');\n      expect(container.firstChild.firstChild.firstChild.tagName).toBe('LABEL');\n      expect(container.firstChild.firstChild.firstChild.innerHTML).toBe(\n        '<input type=\"checkbox\">The title is abc',\n      );\n      expect(container.querySelector('input').checked).toBe(false);\n    });\n\n    class BasicComponent1c extends Component<{\n      isEnabled: boolean;\n      title: string;\n      type: string;\n    }> {\n      render() {\n        const template = (isEnabled, title, type) =>\n          createElement(\n            'div',\n            {\n              className: 'basic',\n            },\n            createElement(\n              'label',\n              {},\n              createElement('input', {\n                type,\n                disabled: !isEnabled,\n              }),\n              'The title is ',\n              title,\n            ),\n          );\n        return template(\n          this.props.isEnabled,\n          this.props.title,\n          this.props.type,\n        );\n      }\n    }\n\n    it('should render a basic component with input tag and attributes', () => {\n      const template = (Component, title, isEnabled) =>\n        createElement(\n          'div',\n          null,\n          createElement(Component, {\n            title,\n            isEnabled,\n            type: 'password',\n          }),\n        );\n\n      render(template(BasicComponent1c, 'abc', true), container);\n      expect(container.firstChild.firstChild.tagName).toBe('DIV');\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n        'basic',\n      );\n      expect(container.firstChild.firstChild.firstChild.tagName).toBe('LABEL');\n      expect(\n        container.firstChild.firstChild.firstChild.firstChild.tagName,\n      ).toBe('INPUT');\n      expect(\n        container.firstChild.firstChild.firstChild.firstChild.getAttribute(\n          'type',\n        ),\n      ).toBe('password');\n      expect(\n        container.firstChild.firstChild.firstChild.firstChild.disabled,\n      ).toBe(false);\n      expect(container.firstChild.firstChild.firstChild.textContent).toBe(\n        'The title is abc',\n      );\n      render(template(BasicComponent1c, ['abc'], true), container);\n      expect(container.firstChild.firstChild.tagName).toBe('DIV');\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n        'basic',\n      );\n      expect(container.firstChild.firstChild.firstChild.tagName).toBe('LABEL');\n      expect(\n        container.firstChild.firstChild.firstChild.firstChild.tagName,\n      ).toBe('INPUT');\n      expect(\n        container.firstChild.firstChild.firstChild.firstChild.getAttribute(\n          'type',\n        ),\n      ).toBe('password');\n      expect(\n        container.firstChild.firstChild.firstChild.firstChild.disabled,\n      ).toBe(false);\n      expect(container.firstChild.firstChild.firstChild.textContent).toBe(\n        'The title is abc',\n      );\n    });\n\n    class BasicComponent1d extends Component<{\n      isDisabled: boolean;\n      title: string;\n    }> {\n      render() {\n        const template = (isDisabled, title) =>\n          createElement(\n            'div',\n            { className: 'basic' },\n            createElement(\n              'label',\n              {},\n              createElement('input', {\n                disabled: isDisabled,\n                type: 'password',\n              }),\n              'The title is ',\n              title,\n            ),\n          );\n        return template(this.props.isDisabled, this.props.title);\n      }\n    }\n\n    it('should render a basic component with inputs #3 #3', () => {\n      const template = (Component, title, isDisabled) =>\n        createElement(\n          'div',\n          null,\n          createElement(Component, { title, isDisabled }),\n        );\n      render(template(BasicComponent1d, 'abc', true), container);\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"basic\"><label><input disabled=\"\" type=\"password\">The title is abc</label></div></div>',\n      );\n      expect(container.querySelector('input').disabled).toBe(true);\n\n      render(template(BasicComponent1d, '123', false), container);\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"basic\"><label><input type=\"password\">The title is 123</label></div></div>',\n      );\n      expect(container.querySelector('input').disabled).toBe(false);\n    });\n\n    it('should render a basic component and remove property if null #1', () => {\n      const template = (Component, title, name) =>\n        createElement('div', null, createElement(Component, { title, name }));\n\n      render(template(BasicComponent1, 'abc', 'basic-render'), container);\n\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"basic\"><span class=\"basic-render\">The title is abc</span></div></div>',\n      );\n\n      render(template(BasicComponent1, '123', null), container);\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"basic\"><span>The title is 123</span></div></div>',\n      );\n    });\n\n    it('should render a basic component and remove property if null #2', () => {\n      const template = (Component, title, name) =>\n        createElement('div', null, createElement(Component, { title, name }));\n\n      render(template(BasicComponent1, 'abc', null), container);\n\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"basic\"><span>The title is abc</span></div></div>',\n      );\n\n      render(null, container);\n\n      render(template(BasicComponent1, '123', 'basic-update'), container);\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"basic\"><span class=\"basic-update\">The title is 123</span></div></div>',\n      );\n    });\n\n    it('should render a basic root component', () => {\n      const template = (Component, title, name) =>\n        createElement(Component, { title, name });\n\n      render(template(BasicComponent1, 'abc', 'basic-render'), container);\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"basic\"><span class=\"basic-render\">The title is abc</span></div>',\n      );\n      render(template(BasicComponent1, 'abc', 'basic-render'), container);\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"basic\"><span class=\"basic-render\">The title is abc</span></div>',\n      );\n\n      render(template(BasicComponent1, 'abc', {}), container);\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"basic\"><span class=\"[object Object]\">The title is abc</span></div>',\n      );\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    class BasicComponent2 extends Component<{\n      name: string;\n      title: string;\n      children: any;\n    }> {\n      render() {\n        const template = (name, title, children) =>\n          createElement(\n            'div',\n            {\n              className: 'basic',\n            },\n            createElement(\n              'span',\n              {\n                className: name,\n              },\n              'The title is ',\n              title,\n            ),\n            children,\n          );\n        return template(this.props.name, this.props.title, this.props.children);\n      }\n    }\n\n    it('should render a basic component with children', () => {\n      const template = (Component, title, name) =>\n        createElement(\n          'div',\n          null,\n          createElement(\n            Component,\n            {\n              title,\n              name,\n            },\n            createElement('span', null, \"I'm a child\"),\n          ),\n        );\n\n      render(template(BasicComponent2, 'abc', 'basic-render'), container);\n\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"basic\"><span class=\"basic-render\">The title is abc</span><span>I\\'m a child</span></div></div>',\n      );\n      render(template(BasicComponent2, 'abc', 'basic-render'), container);\n\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"basic\"><span class=\"basic-render\">The title is abc</span><span>I\\'m a child</span></div></div>',\n      );\n\n      render(template(BasicComponent2, '123', 'basic-update'), container);\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"basic\"><span class=\"basic-update\">The title is 123</span><span>I\\'m a child</span></div></div>',\n      );\n      render(template(BasicComponent2, '1234', 'basic-update'), container);\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"basic\"><span class=\"basic-update\">The title is 1234</span><span>I\\'m a child</span></div></div>',\n      );\n    });\n\n    class BasicComponent2b extends Component {\n      render() {\n        const template = (children) =>\n          createElement(\n            'div',\n            null,\n            createElement('span', null, 'component!'),\n            createElement('div', null, children),\n          );\n        return template(this.props.children);\n      }\n    }\n\n    class BasicComponent2c extends Component {\n      render() {\n        const template = (children) =>\n          createElement(\n            'div',\n            null,\n            createElement('span', null, 'other component!'),\n            createElement('div', null, children),\n          );\n        return template(this.props.children);\n      }\n    }\n\n    class BasicComponent3 extends Component<{ styles: any; title: string }> {\n      render() {\n        const template = (styles, title) =>\n          createElement(\n            'div',\n            {\n              style: styles,\n            },\n            createElement(\n              'span',\n              {\n                style: styles,\n              },\n              'The title is ',\n              title,\n            ),\n          );\n\n        return template(this.props.styles, this.props.title);\n      }\n    }\n\n    if (typeof global !== 'undefined' && !global.usingJSDOM) {\n      it('should render a basic component with styling', () => {\n        const template = (Component, props) => createElement(Component, props);\n\n        render(\n          template(BasicComponent3, {\n            title: 'styled!',\n            styles: {\n              color: 'red',\n              'padding-left': '10px',\n            },\n          }),\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div style=\"color: red; padding-left: 10px;\"><span style=\"color: red; padding-left: 10px;\">The title is styled!</span></div>',\n        );\n        render(\n          template(BasicComponent3, {\n            title: 'styled!',\n            styles: {\n              color: 'red',\n              'padding-left': '10px',\n            },\n          }),\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div style=\"color: red; padding-left: 10px;\"><span style=\"color: red; padding-left: 10px;\">The title is styled!</span></div>',\n        );\n\n        render(\n          template(BasicComponent3, {\n            title: 'styled (again)!',\n            styles: {\n              color: 'blue',\n              'padding-right': '20px',\n            },\n          }),\n          container,\n        );\n        expect(container.innerHTML).toBe(\n          '<div style=\"color: blue; padding-right: 20px;\"><span style=\"color: blue; padding-right: 20px;\">The title is styled (again)!</span></div>',\n        );\n      });\n    }\n\n    it('should render a basic component with component children', () => {\n      const template = (Component1, Component2, Component3) =>\n        createElement(\n          Component1,\n          null,\n          createElement(Component2, null, createElement(Component3, null)),\n        );\n      render(\n        template(BasicComponent2b, BasicComponent2b, BasicComponent2b),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<div><span>component!</span><div><div><span>component!</span><div><div><span>component!</span><div></div></div></div></div></div></div>',\n      );\n\n      render(null, container);\n\n      render(\n        template(BasicComponent2b, BasicComponent2b, BasicComponent2b),\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div><span>component!</span><div><div><span>component!</span><div><div><span>component!</span><div></div></div></div></div></div></div>',\n      );\n\n      render(\n        template(BasicComponent2b, BasicComponent2b, BasicComponent2c),\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div><span>component!</span><div><div><span>component!</span><div><div><span>other component!</span><div></div></div></div></div></div></div>',\n      );\n\n      render(\n        template(BasicComponent2b, BasicComponent2c, BasicComponent2c),\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div><span>component!</span><div><div><span>other component!</span><div><div><span>other component!</span><div></div></div></div></div></div></div>',\n      );\n\n      render(\n        template(BasicComponent2b, BasicComponent2c, BasicComponent2c),\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div><span>component!</span><div><div><span>other component!</span><div><div><span>other component!</span><div></div></div></div></div></div></div>',\n      );\n\n      render(\n        template(BasicComponent2c, BasicComponent2c, BasicComponent2c),\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div><span>other component!</span><div><div><span>other component!</span><div><div><span>other component!</span><div></div></div></div></div></div></div>',\n      );\n      render(\n        template(BasicComponent2c, BasicComponent2c, BasicComponent2c),\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div><span>other component!</span><div><div><span>other component!</span><div><div><span>other component!</span><div></div></div></div></div></div></div>',\n      );\n    });\n\n    it('should render a basic component and correctly mount', () => {\n      let componentWillMountCount;\n\n      class ComponentLifecycleCheck extends Component {\n        render() {\n          const _template = (children) =>\n            createElement(\n              'div',\n              null,\n              createElement('span', null, 'component!'),\n              createElement('div', null, children),\n            );\n          return _template(this.props.children);\n        }\n\n        componentWillMount() {\n          componentWillMountCount++;\n        }\n      }\n\n      componentWillMountCount = 0;\n      const template = (Component1, Component2, Component3) =>\n        createElement(\n          Component1,\n          null,\n          createElement(Component2, null, createElement(Component3, null)),\n        );\n\n      render(\n        template(\n          ComponentLifecycleCheck,\n          ComponentLifecycleCheck,\n          ComponentLifecycleCheck,\n        ),\n        container,\n      );\n      expect(componentWillMountCount).toBe(3);\n\n      render(\n        template(\n          ComponentLifecycleCheck,\n          ComponentLifecycleCheck,\n          ComponentLifecycleCheck,\n        ),\n        container,\n      );\n      expect(componentWillMountCount).toBe(3);\n    });\n\n    describe('should render multiple components', () => {\n      it('should render multiple components', () => {\n        const template = (\n          Component,\n          title1,\n          name1,\n          Component2,\n          title2,\n          name2,\n        ) =>\n          createElement(\n            'div',\n            null,\n            createElement(Component, {\n              title: title1,\n              name: name1,\n            }),\n            createElement(Component2, {\n              title: title2,\n              name: name2,\n            }),\n          );\n\n        render(\n          template(\n            BasicComponent1,\n            'component 1',\n            'basic-render',\n            BasicComponent1,\n            'component 2',\n            'basic-render',\n          ),\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div><div class=\"basic\"><span class=\"basic-render\">The title is component 1</span></div>' +\n            '<div class=\"basic\"><span class=\"basic-render\">The title is component 2</span></div></div>',\n        );\n\n        render(\n          template(\n            BasicComponent1,\n            'component 1',\n            'basic-render',\n            BasicComponent1,\n            'component 2',\n            'basic-render',\n          ),\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div><div class=\"basic\"><span class=\"basic-render\">The title is component 1</span></div>' +\n            '<div class=\"basic\"><span class=\"basic-render\">The title is component 2</span></div></div>',\n        );\n      });\n    });\n\n    it('should mount and unmount a basic component', () => {\n      let mountCount;\n      let unmountCount;\n\n      class ComponentLifecycleCheck extends Component {\n        render() {\n          const _template = () =>\n            createElement('div', null, createElement('span', null));\n          return _template();\n        }\n\n        componentDidMount() {\n          mountCount++;\n        }\n\n        componentWillUnmount() {\n          unmountCount++;\n        }\n      }\n\n      mountCount = 0;\n      unmountCount = 0;\n      const template = (Component) => createElement(Component, null);\n      render(template(ComponentLifecycleCheck), container);\n\n      expect(mountCount).toBe(1);\n      render(null, container);\n      expect(unmountCount).toBe(1);\n    });\n\n    it('should mount and unmount a basic component #2', () => {\n      let mountCount;\n      let unmountCount;\n\n      class ComponentLifecycleCheck extends Component {\n        render() {\n          return createElement('div', null, createElement('span', null));\n        }\n\n        componentDidMount() {\n          mountCount++;\n        }\n\n        componentWillUnmount() {\n          unmountCount++;\n        }\n      }\n\n      mountCount = 0;\n      unmountCount = 0;\n\n      render(createElement(ComponentLifecycleCheck, null), container);\n      expect(mountCount).toBe(1);\n      render(null, container);\n      expect(unmountCount).toBe(1);\n      render(createElement(ComponentLifecycleCheck, null), container);\n      expect(mountCount).toBe(2);\n      render(null, container);\n      expect(unmountCount).toBe(2);\n    });\n\n    describe('state changes should trigger all lifecycle events for an update', () => {\n      let componentWillMountCount;\n      let template;\n\n      interface CounterState {\n        counter: number;\n      }\n\n      class ComponentLifecycleCheck extends Component<any, CounterState> {\n        state: CounterState;\n\n        constructor() {\n          super(null);\n          this.state = {\n            counter: 0,\n          };\n        }\n\n        render() {\n          const _template = (counter) =>\n            createElement('div', null, createElement('span', {}, counter));\n          return _template(this.state.counter);\n        }\n\n        componentWillMount() {\n          componentWillMountCount++;\n          this.setState({\n            counter: this.state.counter + 1,\n          });\n        }\n      }\n\n      beforeEach(() => {\n        componentWillMountCount = 0;\n        template = (Component) => createElement(Component, null);\n        render(template(ComponentLifecycleCheck), container);\n      });\n\n      it('componentWillMountCount to have fired once', () => {\n        expect(componentWillMountCount).toBe(1);\n      });\n      it('the element in the component should show the new state', () => {\n        expect(container.innerHTML).toBe('<div><span>1</span></div>');\n      });\n    });\n\n    describe('state changes should trigger all lifecycle events for an update #2', () => {\n      let componentWillMountCount;\n      let shouldComponentUpdateCount;\n      let componentDidUpdateCount;\n      let componentWillUpdateCount;\n      let template;\n      let update;\n\n      interface CounterState {\n        counter: number;\n      }\n\n      class ComponentLifecycleCheck extends Component<any, CounterState> {\n        state: CounterState;\n        constructor() {\n          super(null);\n          this.state = {\n            counter: 0,\n          };\n\n          update = () => {\n            this.setState({\n              counter: this.state.counter + 1,\n            });\n          };\n        }\n\n        render() {\n          const _template = (counter) =>\n            createElement('div', null, createElement('span', {}, counter));\n          return _template(this.state.counter);\n        }\n\n        componentWillMount() {\n          componentWillMountCount++;\n        }\n\n        shouldComponentUpdate() {\n          shouldComponentUpdateCount++;\n          return true;\n        }\n\n        componentDidUpdate() {\n          componentDidUpdateCount++;\n        }\n\n        componentWillUpdate() {\n          componentWillUpdateCount++;\n        }\n      }\n\n      beforeEach(() => {\n        componentWillMountCount = 0;\n        shouldComponentUpdateCount = 0;\n        componentDidUpdateCount = 0;\n        componentWillUpdateCount = 0;\n        template = (Component) => createElement(Component, null);\n        render(template(ComponentLifecycleCheck), container);\n        update();\n      });\n\n      it('componentWillMountCount to have fired once', () => {\n        expect(componentWillMountCount).toBe(1);\n      });\n      it('shouldComponentUpdateCount to have fired once', () => {\n        expect(shouldComponentUpdateCount).toBe(1);\n      });\n      it('componentWillUpdateCount to have fired once', () => {\n        expect(componentWillUpdateCount).toBe(1);\n      });\n      it('componentDidUpdateCount to have fired once', () => {\n        expect(componentDidUpdateCount).toBe(1);\n      });\n      it('the element in the component should show the new state', () => {\n        expect(container.innerHTML).toBe('<div><span>1</span></div>');\n      });\n    });\n\n    describe('should render a basic component with conditional fragment', () => {\n      const tpl3625453295 = function () {\n        return createElement('h1', null, 'BIG');\n      };\n      const tpl4021787591 = function () {\n        return createElement('h2', null, 'small');\n      };\n\n      class ConditionalComponent extends Component<{ condition: boolean }> {\n        render() {\n          return createElement('div', null, [\n            this.props.condition ? tpl3625453295() : tpl4021787591(),\n            createElement('p', null, 'test'),\n          ]);\n        }\n      }\n\n      it('Initial render (creation)', () => {\n        render(\n          createElement(ConditionalComponent, { condition: true }),\n          container,\n        );\n        expect(container.innerHTML).toBe('<div><h1>BIG</h1><p>test</p></div>');\n        render(\n          createElement(ConditionalComponent, { condition: false }),\n          container,\n        );\n        expect(container.innerHTML).toBe(\n          '<div><h2>small</h2><p>test</p></div>',\n        );\n      });\n    });\n\n    describe('should render a basic component with a list of values from state', () => {\n      const tpl2026545261 = function (v0) {\n        return createElement(\n          'ul',\n          { class: 'login-organizationlist' },\n          '',\n          v0,\n          '',\n        );\n      };\n      const tpl3192647933 = function (v0) {\n        return createElement('li', null, v0);\n      };\n      const tpl1546018623 = function (v0) {\n        return createElement(v0, null);\n      };\n\n      interface ValueState {\n        organizations: { name: string; key: string | number }[];\n      }\n      class ValueComponent extends Component<any, ValueState> {\n        state: ValueState;\n\n        constructor(props) {\n          super(props);\n          this.state = {\n            organizations: [\n              { name: 'test1', key: '1' },\n              { name: 'test2', key: 2 },\n              { name: 'test3', key: '3' },\n              { name: 'test4', key: '4' },\n              { name: 'test5', key: '5' },\n              { name: 'test6', key: '6' },\n            ],\n          };\n        }\n\n        render() {\n          return tpl2026545261(\n            this.state.organizations.map(function (result) {\n              return tpl3192647933(result.name);\n            }),\n          );\n        }\n      }\n\n      it('Initial render (creation)', () => {\n        render(tpl1546018623(ValueComponent), container);\n        expect(container.innerHTML).toBe(\n          '<ul class=\"login-organizationlist\"><li>test1</li><li>test2</li><li>test3</li><li>test4</li><li>test5</li><li>test6</li></ul>',\n        );\n        render(tpl1546018623(ValueComponent), container);\n        expect(container.innerHTML).toBe(\n          '<ul class=\"login-organizationlist\"><li>test1</li><li>test2</li><li>test3</li><li>test4</li><li>test5</li><li>test6</li></ul>',\n        );\n        render(tpl1546018623(ValueComponent), container);\n        expect(container.innerHTML).toBe(\n          '<ul class=\"login-organizationlist\"><li>test1</li><li>test2</li><li>test3</li><li>test4</li><li>test5</li><li>test6</li></ul>',\n        );\n      });\n    });\n\n    describe('BasicStateless', () => {\n      function BasicStatelessComponent1({ name, title }) {\n        const template = (_name, _title) =>\n          createElement(\n            'div',\n            {\n              className: 'basic',\n            },\n            createElement(\n              'span',\n              {\n                className: _name,\n              },\n              'The title is ',\n              _title,\n            ),\n          );\n        return template(name, title);\n      }\n\n      it('should render a stateless component', () => {\n        const template = (Component, title) =>\n          createElement(\n            'div',\n            null,\n            createElement(Component, {\n              title,\n              name: 'Hello, World!',\n            }),\n          );\n\n        render(template(BasicStatelessComponent1, 'abc'), container);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n          'basic',\n        );\n        expect(\n          container.firstChild.firstChild.firstChild.getAttribute('class'),\n        ).toBe('Hello, World!');\n        expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n        expect(container.firstChild.firstChild.firstChild.textContent).toBe(\n          'The title is abc',\n        );\n        render(template(BasicStatelessComponent1, null), container);\n        render(template(BasicStatelessComponent1, 'abc'), container);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n          'basic',\n        );\n        expect(\n          container.firstChild.firstChild.firstChild.getAttribute('class'),\n        ).toBe('Hello, World!');\n        expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n        expect(container.firstChild.firstChild.firstChild.textContent).toBe(\n          'The title is abc',\n        );\n\n        render(template(BasicStatelessComponent1, undefined), container);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n          'basic',\n        );\n        expect(\n          container.firstChild.firstChild.firstChild.getAttribute('class'),\n        ).toBe('Hello, World!');\n        expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n        expect(container.firstChild.firstChild.firstChild.textContent).toBe(\n          'The title is ',\n        );\n\n        render(template(BasicStatelessComponent1, undefined), container);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.firstChild.getAttribute('class')).toBe(\n          'basic',\n        );\n        expect(\n          container.firstChild.firstChild.firstChild.getAttribute('class'),\n        ).toBe('Hello, World!');\n        expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n        expect(container.firstChild.firstChild.firstChild.textContent).toBe(\n          'The title is ',\n        );\n      });\n    });\n\n    describe('should render a component with a conditional state item', () => {\n      const tpl3578458729 = function (v0) {\n        return createElement('div', { className: 'login-view bg-visma' }, v0);\n      };\n      const tpl188998005 = function () {\n        return createElement('div', null, 'VISIBLE');\n      };\n\n      const tpl3754840163 = function (v0) {\n        return createElement(\n          'div',\n          null,\n          createElement('button', { onclick: v0 }, 'Make visible'),\n        );\n      };\n\n      class TEST extends Component {\n        // @ts-ignore it does not understand meaning of call(this)\n        private makeVisible: () => void;\n\n        constructor(props) {\n          super(props);\n          this.state = {\n            show: false,\n          };\n\n          this.makeVisible = function () {\n            this.setState({\n              show: true,\n            });\n          }.bind(this);\n        }\n\n        render() {\n          return tpl3578458729(\n            function () {\n              if (this.state.show === true) {\n                return tpl188998005();\n              } else {\n                return tpl3754840163(this.makeVisible);\n              }\n            }.call(this),\n          );\n        }\n      }\n\n      const tpl79713834 = function (v0) {\n        return createElement(v0, null);\n      };\n\n      it('Initial render (creation)', () => {\n        render(tpl79713834(TEST), container);\n        expect(container.innerHTML).toBe(\n          '<div class=\"login-view bg-visma\"><div><button>Make visible</button></div></div>',\n        );\n      });\n\n      it('Second render (update with state change)', (done) => {\n        render(tpl79713834(TEST), container);\n        render(tpl79713834(TEST), container);\n        const buttons = container.querySelectorAll('button');\n\n        for (const button of buttons) {\n          button.click();\n        }\n\n        setTimeout(() => {\n          expect(container.innerHTML).toBe(\n            '<div class=\"login-view bg-visma\"><div>VISIBLE</div></div>',\n          );\n          done();\n        }, 25);\n      });\n    });\n\n    describe('should render a component with a list of divs', () => {\n      const BaseView = function (v0, v1) {\n        return createElement(\n          'div',\n          { class: 'login-view' },\n          createElement('button', { onclick: v0 }, 'ADD'),\n          createElement('br', null),\n          v1,\n        );\n      };\n\n      const Looper = function (v0) {\n        return createElement('div', null, createElement('h1', null, v0));\n      };\n\n      const starter = function (v0) {\n        return createElement(v0, null);\n      };\n\n      class SomeError extends Component {\n        constructor(props) {\n          super(props);\n          this.state = {\n            list: ['SS', 'SS1'],\n          };\n        }\n\n        render() {\n          /* eslint new-cap:0 */\n          return BaseView(\n            undefined,\n            function () {\n              return this.state.list.map(function (result) {\n                return Looper(result);\n              });\n            }.call(this),\n          );\n        }\n      }\n\n      it('Initial render (creation)', () => {\n        render(starter(SomeError), container);\n\n        expect(container.innerHTML).toBe(\n          '<div class=\"login-view\"><button>ADD</button><br><div><h1>SS</h1></div><div><h1>SS1</h1></div></div>',\n        );\n\n        render(starter(SomeError), container);\n\n        expect(container.innerHTML).toBe(\n          '<div class=\"login-view\"><button>ADD</button><br><div><h1>SS</h1></div><div><h1>SS1</h1></div></div>',\n        );\n      });\n    });\n\n    describe('should render a component with a list of text nodes', () => {\n      const root = function (children) {\n        return createElement('div', null, children);\n      };\n\n      const header = function (children) {\n        return createElement('div', null, children);\n      };\n\n      const view = function (state) {\n        return root([state ? header(['Foo']) : header(['Bar', 'Qux'])]);\n      };\n\n      it('Initial render (creation)', () => {\n        render(view(true), container);\n        expect(container.innerHTML).toBe('<div><div>Foo</div></div>');\n      });\n      it('Second render (update)', () => {\n        render(view(true), container);\n        render(view(false), container);\n        expect(container.innerHTML).toBe('<div><div>BarQux</div></div>');\n      });\n    });\n\n    describe('SetState function callback', () => {\n      it('Should have state, props, and context as parameters', (done) => {\n        function checkParams(state, props, context) {\n          expect(state).toEqual({ btnstate: 'btnstate' });\n          expect(props).toEqual({ buttonProp: 'magic', children: 'btn' });\n          expect(context).toEqual({ color: 'purple' });\n          done();\n        }\n\n        class Button extends Component {\n          constructor(props) {\n            super(props);\n            this.state = {\n              btnstate: 'btnstate',\n            };\n          }\n\n          click() {\n            this.setState(checkParams);\n          }\n\n          render() {\n            return createElement(\n              'button',\n              {\n                onClick: this.click.bind(this),\n                style: {\n                  background: this.context.color,\n                },\n              },\n              this.props.children,\n            );\n          }\n        }\n\n        class Message extends Component<{ text: string }> {\n          render() {\n            return createElement('div', null, [\n              this.props.text,\n              createElement(Button, { buttonProp: 'magic' }, 'btn'),\n            ]);\n          }\n        }\n\n        class MessageList extends Component<{ messages: { text: string }[] }> {\n          getChildContext() {\n            return { color: 'purple' };\n          }\n\n          render() {\n            const children = this.props.messages.map(function (message) {\n              return createElement(Message, { text: message.text });\n            });\n\n            return createElement('div', null, children);\n          }\n        }\n\n        render(\n          createElement(MessageList, {\n            messages: [{ text: 'eka' }, { text: 'toka' }],\n          }),\n          container,\n        );\n\n        container.querySelector('button').click();\n      });\n    });\n  }\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/components1.spec.tsx",
    "content": "import { Component, render } from 'inferno';\n\ndescribe('Components 1 (JSX)', () => {\n  let container;\n  let attachedListener: () => void = () => {};\n  let renderedName: string | null = null;\n\n  interface InnerProps {\n    onClick: () => void;\n    name: null | string;\n  }\n\n  class Inner extends Component<InnerProps> {\n    render() {\n      attachedListener = this.props.onClick;\n      renderedName = this.props.name;\n      return <div className={this.props.name} />;\n    }\n  }\n\n  beforeEach(function () {\n    attachedListener = () => {};\n    renderedName = null;\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    document.body.removeChild(container);\n  });\n\n  class BasicComponent1 extends Component<{ name: any; title: any }> {\n    render() {\n      return (\n        <div className=\"basic\">\n          <span className={this.props.name}>\n            The title is {this.props.title}\n          </span>\n        </div>\n      );\n    }\n  }\n\n  it('should render a basic component jsx', () => {\n    render(\n      <div>\n        <BasicComponent1 title=\"abc\" name=\"basic-render\" />\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span class=\"basic-render\">The title is abc</span></div></div>',\n    );\n\n    render(\n      <div>\n        <BasicComponent1 title=\"abc\" name=\"basic-render\" />\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span class=\"basic-render\">The title is abc</span></div></div>',\n    );\n\n    const attrs = { title: 'abc', name: 'basic-render2', foo: 'bar' };\n\n    // JSX Spread Attribute\n    render(\n      <div>\n        <BasicComponent1 {...attrs} />\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span class=\"basic-render2\">The title is abc</span></div></div>',\n    );\n  });\n\n  class BasicComponent1b extends Component<{\n    isChecked: boolean | null;\n    title: string;\n  }> {\n    render() {\n      return (\n        <div className=\"basic\">\n          <label>\n            <input checked={this.props.isChecked} />\n            The title is {this.props.title}\n          </label>\n        </div>\n      );\n    }\n  }\n\n  it('should render a basic component with inputs', () => {\n    render(\n      <div>\n        <BasicComponent1b title=\"abc\" isChecked={true} />\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><label><input>The title is abc</label></div></div>',\n    );\n    expect(container.querySelector('input').checked).toBe(true);\n\n    render(\n      <div>\n        <BasicComponent1b title=\"123\" isChecked={false} />\n      </div>,\n      container,\n    );\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><label><input>The title is 123</label></div></div>',\n    );\n    expect(container.querySelector('input').checked).toBe(false);\n\n    render(\n      <div>\n        <BasicComponent1b title=\"123\" isChecked={null} />\n      </div>,\n      container,\n    );\n\n    render(<div />, container);\n\n    render(\n      <div>\n        <BasicComponent1b title=\"123\" isChecked={true} />\n      </div>,\n      container,\n    );\n    expect(container.querySelector('input').checked).toBe(true);\n  });\n\n  it('should render a basic component and remove property if null', () => {\n    render(\n      <div>\n        <BasicComponent1 title=\"abc\" name=\"basic-render\" />\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span class=\"basic-render\">The title is abc</span></div></div>',\n    );\n\n    render(<div />, container);\n    render(\n      <div>\n        <BasicComponent1 title=\"Hello, World!\" name=\"basic-render\" />\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span class=\"basic-render\">The title is Hello, World!</span></div></div>',\n    );\n\n    render(\n      <div>\n        <BasicComponent1 title=\"123\" name={null} />\n      </div>,\n      container,\n    );\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span>The title is 123</span></div></div>',\n    );\n    render(\n      <div>\n        <BasicComponent1 title={[]} name={null} />\n      </div>,\n      container,\n    );\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span>The title is </span></div></div>',\n    );\n\n    render(\n      <div>\n        <BasicComponent1 title={null} name={null} />\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span>The title is </span></div></div>',\n    );\n\n    render(\n      <div>\n        <BasicComponent1 title=\"abc\" name={null} />\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span>The title is abc</span></div></div>',\n    );\n\n    render(\n      <div>\n        <BasicComponent1 title=\"123\" name=\"basic-update\" />\n      </div>,\n      container,\n    );\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span class=\"basic-update\">The title is 123</span></div></div>',\n    );\n  });\n\n  it('should render a basic root component', () => {\n    render(<BasicComponent1 title=\"abc\" name=\"basic-render\" />, container);\n\n    expect(container.firstChild.getAttribute('class')).toBe('basic');\n\n    render(<BasicComponent1 title=\"abc\" name=\"basic-render\" />, container);\n\n    expect(container.firstChild.getAttribute('class')).toBe('basic');\n\n    render(<BasicComponent1 title=\"123\" name=\"basic-update\" />, container);\n    expect(container.innerHTML).toBe(\n      '<div class=\"basic\"><span class=\"basic-update\">The title is 123</span></div>',\n    );\n  });\n\n  class BasicComponent2 extends Component<{ name: string; title: string }> {\n    render() {\n      return (\n        <div className=\"basic\">\n          <span className={this.props.name}>\n            The title is {this.props.title}\n          </span>\n          {this.props.children}\n        </div>\n      );\n    }\n  }\n\n  it('should render a basic component with children', () => {\n    render(\n      <div>\n        <BasicComponent2 title=\"abc\" name=\"basic-render\">\n          <span>Im a child</span>\n        </BasicComponent2>\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span class=\"basic-render\">The title is abc</span><span>Im a child</span></div></div>',\n    );\n\n    render(\n      <div>\n        <BasicComponent2 title=\"123\" name=\"basic-update\">\n          <span>Im a child</span>\n        </BasicComponent2>\n      </div>,\n      container,\n    );\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span class=\"basic-update\">The title is 123</span><span>Im a child</span></div></div>',\n    );\n  });\n\n  it('should render multiple components', () => {\n    render(\n      <div>\n        <BasicComponent1 title=\"component 1\" name=\"basic-render\" />\n        <BasicComponent1 title=\"component 2\" name=\"basic-render\" />\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span class=\"basic-render\">The title is component 1</span></div>' +\n        '<div class=\"basic\"><span class=\"basic-render\">The title is component 2</span></div></div>',\n    );\n\n    render(\n      <div>\n        <BasicComponent1 title=\"component 1\" name=\"basic-render\" />\n      </div>,\n      container,\n    );\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"basic\"><span class=\"basic-render\">The title is component 1</span></div></div>',\n    );\n  });\n\n  class BasicComponent3 extends Component<{ title?: string; styles?: any }> {\n    render() {\n      return (\n        <div style={this.props.styles}>\n          <span style={this.props.styles}>The title is {this.props.title}</span>\n        </div>\n      );\n    }\n  }\n\n  it('should render a basic component with styling', () => {\n    render(\n      <BasicComponent3\n        title=\"styled!\"\n        styles={{ color: 'red', 'padding-left': '10px' }}\n      />,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div style=\"color: red; padding-left: 10px;\"><span style=\"color: red; padding-left: 10px;\">The title is styled!</span></div>',\n    );\n\n    render(<BasicComponent3 />, container);\n\n    render(\n      <BasicComponent3\n        title=\"styled (again)!\"\n        styles={{ color: 'blue', 'margin-bottom': '20px' }}\n      />,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div style=\"color: blue; margin-bottom: 20px;\"><span style=\"color: blue; margin-bottom: 20px;\">The title is styled (again)!</span></div>',\n    );\n  });\n\n  it('should render a basic component and remove styling', () => {\n    render(\n      <BasicComponent3\n        title=\"styled!\"\n        styles={{ color: 'red', 'padding-top': '20px' }}\n      />,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div style=\"color: red; padding-top: 20px;\"><span style=\"color: red; padding-top: 20px;\">The title is styled!</span></div>',\n    );\n\n    render(\n      <BasicComponent3 title=\"styles are removed!\" styles={null} />,\n      container,\n    );\n\n    expect([null, '']).toContain(container.firstChild.getAttribute('style'));\n    expect(container.firstChild.tagName).toEqual('DIV');\n    expect(container.firstChild.firstChild.innerHTML).toEqual(\n      'The title is styles are removed!',\n    );\n  });\n\n  interface SuperState {\n    organizations: { name: string; key: string }[];\n  }\n\n  class SuperComponent extends Component<object, SuperState> {\n    state: SuperState;\n\n    constructor(props) {\n      super(props);\n      this.state = {\n        organizations: [\n          { name: 'test1', key: '1' },\n          { name: 'test2', key: '2' },\n          { name: 'test3', key: '3' },\n          { name: 'test4', key: '4' },\n          { name: 'test5', key: '5' },\n          { name: 'test6', key: '6' },\n        ],\n      };\n    }\n\n    render() {\n      return (\n        <ul class=\"login-organizationlist\">\n          {this.state.organizations.map((result) => {\n            return <li>{result.name}</li>;\n          })}\n        </ul>\n      );\n    }\n  }\n\n  it('should render a basic component with a list of values from state', () => {\n    render(<SuperComponent />, container);\n    expect(container.innerHTML).toBe(\n      '<ul class=\"login-organizationlist\"><li>test1</li><li>test2</li><li>test3</li><li>test4</li><li>test5</li><li>test6</li></ul>',\n    );\n  });\n\n  it('should render a basic component with an element and components as children', () => {\n    class Navbar extends Component {\n      render() {\n        return (\n          <ul>\n            <li>Nav1</li>\n          </ul>\n        );\n      }\n    }\n\n    class Main extends Component {\n      render() {\n        return (\n          <div className=\"main\">\n            <Navbar />\n            <div id=\"app\" />\n          </div>\n        );\n      }\n    }\n\n    render(<Main />, container);\n  });\n\n  function test(element, expectedTag, expectedClassName, callback) {\n    render(element, container, () => {\n      expect(container.firstChild).not.toBe(null);\n      expect(container.firstChild.tagName).toBe(expectedTag);\n      expect(container.firstChild.className).toBe(expectedClassName);\n      callback();\n    });\n  }\n\n  it('should only render once when setting state in componentWillMount', function (done) {\n    let renderCount = 0;\n\n    interface FooState {\n      bar: string | null;\n    }\n\n    class Foo extends Component<{ initialValue: string | null }, FooState> {\n      state: FooState;\n\n      constructor(props) {\n        super(props);\n        this.state = { bar: props.initialValue };\n      }\n\n      componentWillMount() {\n        this.setState({ bar: 'bar' });\n      }\n\n      render() {\n        renderCount++;\n        return <span className={this.state.bar} />;\n      }\n    }\n\n    test(<Foo initialValue={null} />, 'SPAN', 'bar', () => {\n      test(<Foo initialValue=\"foo\" />, 'SPAN', 'bar', () => {\n        expect(renderCount).toBe(2);\n        done();\n      });\n    });\n  });\n\n  it('should render with null in the initial state property', function (done) {\n    class Foo extends Component {\n      constructor(props) {\n        super(props);\n        this.state = null;\n      }\n\n      render() {\n        return <span />;\n      }\n    }\n\n    test(<Foo />, 'SPAN', '', done);\n  });\n\n  it('should setState through an event handler', (done) => {\n    interface FooState {\n      bar: string | null;\n    }\n\n    class Foo extends Component<{ initialValue: string | null }, FooState> {\n      state: FooState;\n\n      constructor(props) {\n        super(props);\n        this.state = { bar: props.initialValue };\n      }\n\n      handleClick() {\n        this.setState({ bar: 'bar' });\n      }\n\n      render() {\n        return (\n          <Inner name={this.state.bar} onClick={this.handleClick.bind(this)} />\n        );\n      }\n    }\n\n    test(<Foo initialValue=\"foo\" />, 'DIV', 'foo', () => {\n      expect(renderedName).toBe('foo');\n      attachedListener();\n      setTimeout(() => {\n        expect(renderedName).toBe('bar');\n        done();\n      }, 10);\n    });\n  });\n\n  it('should render using forceUpdate even when there is no state', (done) => {\n    class Foo extends Component<{ initialValue: string | null }> {\n      private mutativeValue: string;\n\n      constructor(props) {\n        super(props);\n        this.mutativeValue = props.initialValue;\n      }\n\n      handleClick() {\n        this.mutativeValue = 'bar';\n        this.forceUpdate();\n      }\n\n      render() {\n        return (\n          <Inner\n            name={this.mutativeValue}\n            onClick={this.handleClick.bind(this)}\n          />\n        );\n      }\n    }\n\n    test(<Foo initialValue=\"foo\" />, 'DIV', 'foo', function () {\n      attachedListener();\n      expect(renderedName).toBe('bar');\n      done();\n    });\n  });\n\n  describe('should render a component with a list of children that dynamically update via setState', () => {\n    interface CounterState {\n      count: number;\n    }\n\n    interface CounterProps {\n      car: string;\n    }\n\n    class Counter extends Component<CounterProps, CounterState> {\n      state: CounterState;\n\n      constructor(props) {\n        super(props);\n        this.state = {\n          count: 0,\n        };\n        this.incrementCount = this.incrementCount.bind(this);\n      }\n\n      incrementCount() {\n        this.setState({\n          count: this.state.count + 1,\n        });\n      }\n\n      render() {\n        return (\n          <div class=\"my-component\">\n            <h1>\n              {this.props.car} {this.state.count}\n            </h1>\n            <button type=\"button\" onClick={this.incrementCount}>\n              Increment\n            </button>\n          </div>\n        );\n      }\n    }\n\n    class Wrapper extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return (\n          <div>\n            {['Saab', 'Volvo', 'BMW'].map(function (c) {\n              return <Counter car={c} />;\n            })}\n          </div>\n        );\n      }\n    }\n\n    it('Initial render (creation)', () => {\n      render(<Wrapper />, container);\n\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"my-component\"><h1>Saab 0</h1><button type=\"button\">Increment</button></div><div class=\"my-component\"><h1>Volvo 0</h1><button type=\"button\">Increment</button></div><div class=\"my-component\"><h1>BMW 0</h1><button type=\"button\">Increment</button></div></div>',\n      );\n    });\n\n    it('Second render (update) #1', (done) => {\n      render(<Wrapper />, container);\n      const buttons = container.querySelectorAll('button');\n      for (const button of buttons) {\n        button.click();\n      }\n\n      setTimeout(() => {\n        expect(container.innerHTML).toBe(\n          '<div><div class=\"my-component\"><h1>Saab 1</h1><button type=\"button\">Increment</button></div><div class=\"my-component\"><h1>Volvo 1</h1><button type=\"button\">Increment</button></div><div class=\"my-component\"><h1>BMW 1</h1><button type=\"button\">Increment</button></div></div>',\n        );\n        done();\n      }, 25);\n    });\n  });\n\n  describe('should render a component with a conditional state item', () => {\n    interface SomeErrorState {\n      show: boolean;\n    }\n\n    class SomeError extends Component<object, SomeErrorState> {\n      state: SomeErrorState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          show: false,\n        };\n\n        this.toggle = this.toggle.bind(this);\n      }\n\n      toggle() {\n        this.setState({\n          show: !this.state.show,\n        });\n      }\n\n      render() {\n        return (\n          <div className=\"login-view bg-visma\">\n            <button onClick={this.toggle}>TOGGLE</button>\n            <br />\n            {function () {\n              if (this.state.show === true) {\n                return <h1>This is cool!</h1>;\n              } else {\n                return <h1>Not so cool</h1>;\n              }\n            }.call(this)}\n          </div>\n        );\n      }\n    }\n\n    it('Initial render (creation)', () => {\n      render(<SomeError />, container);\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"login-view bg-visma\"><button>TOGGLE</button><br><h1>Not so cool</h1></div>',\n      );\n    });\n\n    it('Second render (update with state change) #2', () => {\n      render(<SomeError />, container);\n      const buttons = container.querySelectorAll('button');\n      for (const button of buttons) {\n        button.click();\n      }\n\n      expect(container.innerHTML).toBe(\n        '<div class=\"login-view bg-visma\"><button>TOGGLE</button><br><h1>This is cool!</h1></div>',\n      );\n    });\n  });\n\n  describe('should render a stateless component with a conditional state item', () => {\n    interface TestingState {\n      show: boolean;\n    }\n\n    const StatelessComponent = (props) => <p>{props.name}</p>;\n\n    class Testing extends Component<object, TestingState> {\n      state: TestingState;\n      // @ts-ignore\n      private name: string = 'Kalle';\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          show: false,\n        };\n\n        this.toggle = this.toggle.bind(this);\n      }\n\n      toggle() {\n        this.setState({\n          show: !this.state.show,\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            {function () {\n              if (this.state.show === true) {\n                return <StatelessComponent name={this.name} />;\n              } else {\n                return <h1>Hello folks</h1>;\n              }\n            }.call(this)}\n            <button onClick={this.toggle}>toggle</button>\n          </div>\n        );\n      }\n    }\n\n    it('Initial render (creation)', () => {\n      render(null, container);\n\n      render(<Testing />, container);\n\n      expect(container.innerHTML).toBe(\n        '<div><h1>Hello folks</h1><button>toggle</button></div>',\n      );\n    });\n\n    it('Second render (update with state change) #3', (done) => {\n      render(<Testing />, container);\n      const buttons = container.querySelectorAll('button');\n      for (const button of buttons) {\n        button.click();\n      }\n\n      setTimeout(() => {\n        expect(container.innerHTML).toBe(\n          '<div><p>Kalle</p><button>toggle</button></div>',\n        );\n        done();\n      }, 25);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/components2b.spec.tsx",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('Components 2 (TSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    document.body.removeChild(container);\n  });\n\n  describe('recursive component', () => {\n    it('Should be possible to pass props recursively', () => {\n      interface ListProps {\n        data: Array<{\n          key: string;\n          data: string | Array<{ key: string; data: string }>;\n        }>;\n      }\n      class List extends Component<ListProps> {\n        render() {\n          const children = this.props.data.map((entity) => {\n            const { key, data } = entity;\n            const child = Array.isArray(data) ? (\n              <List data={data} />\n            ) : (\n              <Text data={data as string} />\n            );\n\n            return <li key={key}>{child}</li>;\n          });\n\n          return <ul>{children}</ul>;\n        }\n      }\n\n      interface TextProps {\n        data: string;\n      }\n\n      class Text extends Component<TextProps> {\n        render() {\n          return <span>{this.props.data}</span>;\n        }\n      }\n\n      const data = [\n        { key: '0', data: 'Foo' },\n        {\n          key: '1',\n          data: [\n            { key: '1/1', data: 'a' },\n            { key: '1/2', data: 'b' },\n          ],\n        },\n      ];\n\n      render(<List data={data} />, container);\n      expect(container.innerHTML).toBe(\n        '<ul><li><span>Foo</span></li><li><ul><li><span>a</span></li><li><span>b</span></li></ul></li></ul>',\n      );\n    });\n\n    it('Should be possible to pass props recursively AT BEGINNING (JSX plugin change required)', () => {\n      interface ListProps {\n        data: Array<{\n          key: string;\n          data: string | Array<{ key: string; data: string }>;\n        }>;\n      }\n      class List extends Component<ListProps> {\n        render() {\n          const children = this.props.data.map((entity) => {\n            const { key, data } = entity;\n            const child = Array.isArray(data) ? (\n              <List data={data} />\n            ) : (\n              <Text data={data as string} />\n            );\n\n            return <li key={key}>{child}</li>;\n          });\n\n          return <ul>{children}</ul>;\n        }\n      }\n\n      interface TextProps {\n        data: string;\n      }\n\n      class Text extends Component<TextProps> {\n        render() {\n          return <span>{this.props.data}</span>;\n        }\n      }\n\n      const data = [\n        { key: '0', data: 'Foo' },\n        {\n          key: '1',\n          data: [\n            { key: '1/1', data: 'a' },\n            { key: '1/2', data: 'b' },\n          ],\n        },\n      ];\n\n      render(<List data={data} />, container);\n      expect(container.innerHTML).toBe(\n        '<ul><li><span>Foo</span></li><li><ul><li><span>a</span></li><li><span>b</span></li></ul></li></ul>',\n      );\n    });\n  });\n\n  it('Should render (github #117)', (done) => {\n    interface MakeXState {\n      x: boolean;\n    }\n\n    class MakeX extends Component<object, MakeXState> {\n      state: MakeXState;\n\n      constructor(props) {\n        super(props);\n        this.state = { x: false };\n      }\n\n      componentWillMount() {\n        setTimeout(() => {\n          this.setState({ x: true });\n        }, 10);\n      }\n\n      render() {\n        return <div>{!this.state.x ? <MakeA /> : <MakeY />}</div>;\n      }\n    }\n\n    class MakeY extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return <div>Y</div>;\n      }\n    }\n\n    interface MakeAState {\n      z: boolean;\n    }\n\n    class MakeA extends Component<object, MakeAState> {\n      state: MakeAState;\n\n      constructor(props) {\n        super(props);\n        this.state = { z: false };\n      }\n\n      componentWillMount() {\n        setTimeout(() => {\n          this.setState({ z: true });\n        }, 20);\n      }\n\n      render() {\n        if (!this.state.z) {\n          return <div>A</div>;\n        }\n\n        return <MakeB />;\n      }\n    }\n\n    class MakeB extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return <div>B</div>;\n      }\n    }\n\n    render(<MakeX />, container);\n    setTimeout(function () {\n      done();\n    }, 50);\n  });\n\n  it('Events should propagate between components (github #135)', (done) => {\n    interface LabelProps {\n      text: string;\n    }\n    class Label extends Component<LabelProps> {\n      render() {\n        const style = {\n          'background-color': 'red',\n          padding: '0 20px',\n          fontSize: '40px',\n        };\n        return <span style={style}>{this.props.text}</span>;\n      }\n    }\n\n    let btnFlag = false;\n    let containerFlag = false;\n\n    class Button extends Component<LabelProps> {\n      onClick(_event) {\n        btnFlag = !btnFlag;\n      }\n\n      render() {\n        const { text } = this.props;\n        return (\n          <button onClick={this.onClick}>\n            <Label text={text} />\n          </button>\n        );\n      }\n    }\n\n    class Container extends Component {\n      onClick(_event) {\n        containerFlag = !containerFlag;\n      }\n\n      render() {\n        return (\n          <div onClick={this.onClick}>\n            <Button text=\"Click me\" />\n          </div>\n        );\n      }\n    }\n\n    render(<Container />, container);\n\n    expect(btnFlag).toBe(false);\n    expect(containerFlag).toBe(false);\n\n    const spans = container.querySelectorAll('span');\n    for (const span of spans) {\n      span.click();\n    }\n\n    expect(btnFlag).toBe(true);\n    expect(containerFlag).toBe(true);\n    done();\n  });\n\n  it('Should be possible to stop propagation', (done) => {\n    interface LabelProps {\n      text: string;\n    }\n\n    class Label extends Component<LabelProps> {\n      render() {\n        const style = {\n          'background-color': 'red',\n          padding: '0 20px',\n          fontSize: '40px',\n        };\n        return <span style={style}>{this.props.text}</span>;\n      }\n    }\n\n    let btnFlag = false;\n    let containerFlag = false;\n\n    class Button extends Component<LabelProps> {\n      onClick(event) {\n        event.stopPropagation();\n        btnFlag = !btnFlag;\n      }\n\n      render() {\n        const { text } = this.props;\n        return (\n          <button onClick={this.onClick}>\n            <Label text={text} />\n          </button>\n        );\n      }\n    }\n\n    class Container extends Component {\n      onClick(_event) {\n        containerFlag = !containerFlag;\n      }\n\n      render() {\n        return (\n          <div onClick={this.onClick}>\n            <Button text=\"Click me\" />\n          </div>\n        );\n      }\n    }\n\n    render(<Container />, container);\n\n    expect(btnFlag).toBe(false);\n    expect(containerFlag).toBe(false);\n\n    const spans = container.querySelectorAll('span');\n    for (const span of spans) {\n      span.click();\n    }\n\n    expect(btnFlag).toBe(true);\n    expect(containerFlag).toBe(false);\n    done();\n  });\n\n  describe('Inheritance should work', () => {\n    it('Should render div', () => {\n      class A extends Component {\n        constructor(props) {\n          super(props);\n        }\n      }\n\n      class B extends A {\n        constructor(props) {\n          super(props);\n        }\n      }\n\n      class C extends B {\n        constructor(props) {\n          super(props);\n        }\n\n        render() {\n          return <div />;\n        }\n      }\n\n      render(<C />, container);\n      expect(container.innerHTML).toBe('<div></div>');\n    });\n  });\n\n  describe('A component rendering a component should work as expected', () => {\n    let forceUpdate;\n    let forceUpdate2;\n\n    class Bar extends Component {\n      constructor() {\n        super();\n        forceUpdate = this.forceUpdate.bind(this);\n      }\n\n      render() {\n        return <div>Hello world</div>;\n      }\n    }\n    class Foo extends Component {\n      constructor() {\n        super();\n        forceUpdate2 = this.forceUpdate.bind(this);\n      }\n\n      render() {\n        return <Bar />;\n      }\n    }\n\n    it('should render the div correctly', () => {\n      render(<Foo />, container);\n      expect(container.firstChild.innerHTML).toBe('Hello world');\n    });\n\n    it('should update correctly', () => {\n      render(<Foo />, container);\n      render(<Foo />, container);\n      expect(container.firstChild.innerHTML).toBe('Hello world');\n    });\n\n    it('should update correctly via forceUpdate', () => {\n      render(<Foo />, container);\n      forceUpdate();\n      forceUpdate2();\n      render(<Foo />, container);\n      forceUpdate2();\n      forceUpdate();\n      expect(container.firstChild.innerHTML).toBe('Hello world');\n    });\n  });\n\n  it('Should trigger ref lifecycle after patch', (done) => {\n    let updater;\n    const obj = {\n      fn() {},\n    };\n\n    spyOn(obj, 'fn');\n\n    interface BarState {\n      bool: boolean;\n    }\n\n    class Bar extends Component<object, BarState> {\n      state: BarState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          bool: true,\n        };\n\n        this.changeDOM = this.changeDOM.bind(this);\n        updater = this.changeDOM;\n      }\n\n      changeDOM() {\n        this.setState({\n          bool: !this.state.bool,\n        });\n      }\n\n      render() {\n        if (this.state.bool === true) {\n          return <div>Hello world</div>;\n        } else {\n          return (\n            <div>\n              <div ref={obj.fn}>Hello world2</div>\n            </div>\n          );\n        }\n      }\n    }\n\n    render(<Bar />, container);\n    expect(container.innerHTML).toBe('<div>Hello world</div>');\n    expect(obj.fn).not.toHaveBeenCalled();\n\n    updater();\n    setTimeout(() => {\n      expect(container.innerHTML).toBe('<div><div>Hello world2</div></div>');\n      expect(obj.fn).toHaveBeenCalledTimes(1);\n      done();\n    }, 10);\n  });\n\n  describe('Should be able to swap between invalid node and valid node', () => {\n    it('Should be able to swap between invalid node and valid node', () => {\n      let updater;\n\n      interface BarState {\n        bool: boolean;\n      }\n\n      class Bar extends Component<object, BarState> {\n        state: BarState;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            bool: true,\n          };\n\n          this.changeDOM = this.changeDOM.bind(this);\n          updater = this.changeDOM;\n        }\n\n        changeDOM() {\n          this.setState({\n            bool: !this.state.bool,\n          });\n        }\n\n        render() {\n          if (this.state.bool === true) {\n            return null;\n          } else {\n            return <div>Rendered!</div>;\n          }\n        }\n      }\n\n      render(<Bar />, container);\n      expect(container.innerHTML).toBe('');\n\n      updater();\n      expect(container.innerHTML).toBe('<div>Rendered!</div>');\n\n      updater();\n      expect(container.innerHTML).toBe('');\n\n      updater();\n      expect(container.innerHTML).toBe('<div>Rendered!</div>');\n\n      updater();\n      expect(container.innerHTML).toBe('');\n\n      updater();\n      expect(container.innerHTML).toBe('<div>Rendered!</div>');\n    });\n  });\n\n  it('Should be able to swap between text node and html node', () => {\n    let updater;\n\n    interface BarState {\n      bool: boolean;\n    }\n\n    class Bar extends Component<object, BarState> {\n      state: BarState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          bool: true,\n        };\n\n        this.changeDOM = this.changeDOM.bind(this);\n        updater = this.changeDOM;\n      }\n\n      changeDOM() {\n        this.setState({\n          bool: !this.state.bool,\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            {this.state.bool ? <span>span</span> : 'text'}\n            <div>div</div>\n          </div>\n        );\n      }\n    }\n\n    render(<Bar />, container);\n    expect(container.innerHTML).toBe(\n      '<div><span>span</span><div>div</div></div>',\n    );\n\n    updater();\n    expect(container.innerHTML).toBe('<div>text<div>div</div></div>');\n\n    updater();\n    expect(container.innerHTML).toBe(\n      '<div><span>span</span><div>div</div></div>',\n    );\n\n    updater();\n    expect(container.innerHTML).toBe('<div>text<div>div</div></div>');\n  });\n\n  it('Should be able to swap between text node and html node #2', (done) => {\n    let updater;\n\n    interface BarState {\n      bool: boolean;\n    }\n\n    class Bar extends Component<object, BarState> {\n      state: BarState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          bool: false,\n        };\n\n        this.changeDOM = this.changeDOM.bind(this);\n        updater = this.changeDOM;\n      }\n\n      changeDOM() {\n        this.setState({\n          bool: !this.state.bool,\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            {this.state.bool ? <span>span</span> : ''}\n            <div>div</div>\n          </div>\n        );\n      }\n    }\n\n    render(<Bar />, container);\n    expect(container.innerHTML).toBe('<div><div>div</div></div>');\n\n    updater();\n    setTimeout(() => {\n      expect(container.innerHTML).toBe(\n        '<div><span>span</span><div>div</div></div>',\n      );\n      updater();\n      setTimeout(() => {\n        expect(container.innerHTML).toBe('<div><div>div</div></div>');\n        updater();\n        setTimeout(() => {\n          expect(container.innerHTML).toBe(\n            '<div><span>span</span><div>div</div></div>',\n          );\n          done();\n        }, 10);\n      }, 10);\n    }, 10);\n  });\n\n  describe('handling of sCU', () => {\n    let instance;\n    let shouldUpdate = false;\n\n    interface Test2Props {\n      foo: string;\n    }\n\n    class Test extends Component<Test2Props> {\n      shouldComponentUpdate() {\n        return shouldUpdate;\n      }\n\n      render() {\n        instance = this;\n        return <div contentEditable={true}>{this.props.foo}</div>;\n      }\n    }\n\n    class Test2 extends Component<Test2Props> {\n      shouldComponentUpdate() {\n        return shouldUpdate;\n      }\n\n      render() {\n        instance = this;\n        return createElement('div', { contenteditable: true }, this.props.foo);\n      }\n    }\n\n    it('should correctly render once but never again', () => {\n      shouldUpdate = false;\n      render(<Test foo=\"bar\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">bar</div>');\n      render(<Test foo=\"yar\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">bar</div>');\n      instance.setState({ foo: 'woo' });\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">bar</div>');\n      render(null, container);\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should not fail if text node has external change Github#1207 - createElement', () => {\n      shouldUpdate = false;\n      render(<Test2 foo=\"bar\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">bar</div>');\n      render(<Test2 foo=\"yar\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">bar</div>');\n\n      container.firstChild.removeChild(container.firstChild.firstChild); // When div is contentEditable user can remove whole text content\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\"></div>');\n\n      shouldUpdate = true;\n      render(<Test2 foo=\"foo\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">foo</div>');\n      render(null, container);\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should not fail if text node has external change Github#1207', () => {\n      shouldUpdate = false;\n      render(<Test foo=\"bar\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">bar</div>');\n      render(<Test foo=\"yar\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">bar</div>');\n\n      container.firstChild.removeChild(container.firstChild.firstChild); // When div is contentEditable user can remove whole text content\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\"></div>');\n\n      shouldUpdate = true;\n      render(<Test foo=\"foo\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">foo</div>');\n      render(null, container);\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should not fail if text node has external change Github#1207 (variation - 2)', () => {\n      shouldUpdate = false;\n      render(<Test foo=\"bar\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">bar</div>');\n      render(<Test foo=\"yar\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">bar</div>');\n\n      container.firstChild.removeChild(container.firstChild.firstChild); // When div is contentEditable user can remove whole text content\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\"></div>');\n\n      shouldUpdate = true;\n      render(<Test foo=\"\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\"></div>');\n      render(null, container);\n      expect(container.innerHTML).toBe('');\n    });\n  });\n  describe('handling of different primatives', () => {\n    it('Should correctly handle boolean values (github#255)', () => {\n      const Todo = ({ todo }) => (\n        <tr>\n          <td>{todo.id}</td>\n          <td>{todo.desc}</td>\n          <td>{todo.done}</td>\n        </tr>\n      );\n\n      render(<Todo todo={{ done: false }} />, container);\n      expect(container.innerHTML).toBe('<tr><td></td><td></td><td></td></tr>');\n      render(<Todo todo={{ done: true }} />, container);\n      expect(container.innerHTML).toBe('<tr><td></td><td></td><td></td></tr>');\n    });\n  });\n\n  describe('handling JSX spread attributes', () => {\n    it('should properly handle multiple attributes using spread', () => {\n      class Input extends Component {\n        constructor() {\n          super();\n          this.handleBlur = this.handleBlur.bind(this);\n        }\n\n        handleBlur(_event) {}\n\n        render() {\n          const props = {\n            onBlur: this.handleBlur,\n            className: 'foo',\n            id: 'test',\n          };\n\n          return <input {...props} />;\n        }\n      }\n\n      render(<Input />, container);\n      expect(container.innerHTML).toBe('<input class=\"foo\" id=\"test\">');\n    });\n  });\n\n  describe('Swapping Component to DOM node', () => {\n    it('Should be able to swap statefull component to DOM list when doing setState', () => {\n      let change1;\n      let unMountCalled = false;\n\n      class FooBar extends Component {\n        constructor(props) {\n          super(props);\n        }\n\n        componentWillUnmount() {\n          unMountCalled = true;\n        }\n\n        render() {\n          return (\n            <div>\n              <span>foo1</span>\n              <span>foo2</span>\n              <span>foo3</span>\n              <span>foo4</span>\n            </div>\n          );\n        }\n      }\n\n      interface TesterState {\n        toggle1: boolean;\n      }\n\n      class Tester extends Component<any, TesterState> {\n        state: TesterState;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            toggle1: false,\n          };\n\n          change1 = this.toggle1.bind(this);\n        }\n\n        toggle1() {\n          this.setState({\n            toggle1: !this.state.toggle1,\n          });\n        }\n\n        renderContent() {\n          if (this.state.toggle1) {\n            return <FooBar />;\n          } else {\n            return (\n              <div className=\"login-container\">\n                <h1>foo</h1>\n              </div>\n            );\n          }\n        }\n\n        render() {\n          return <div>{this.renderContent()}</div>;\n        }\n      }\n\n      render(<Tester />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"login-container\"><h1>foo</h1></div></div>',\n      );\n      expect(unMountCalled).toEqual(false);\n      change1();\n      expect(unMountCalled).toEqual(false);\n      expect(container.innerHTML).toBe(\n        '<div><div><span>foo1</span><span>foo2</span><span>foo3</span><span>foo4</span></div></div>',\n      );\n      change1();\n      expect(unMountCalled).toEqual(true);\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"login-container\"><h1>foo</h1></div></div>',\n      );\n    });\n\n    it('Should be able to swap stateless component to DOM list when doing setState', () => {\n      let change1;\n\n      const FooBar = () => (\n        <div>\n          <span>foo1</span>\n          <span>foo2</span>\n          <span>foo3</span>\n          <span>foo4</span>\n        </div>\n      );\n\n      interface TesterState {\n        toggle1: boolean;\n      }\n\n      class Tester extends Component<object, TesterState> {\n        state: TesterState;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            toggle1: false,\n          };\n\n          change1 = this.toggle1.bind(this);\n        }\n\n        toggle1() {\n          this.setState({\n            toggle1: !this.state.toggle1,\n          });\n        }\n\n        renderContent() {\n          if (this.state.toggle1) {\n            return <FooBar />;\n          } else {\n            return (\n              <div className=\"login-container\">\n                <h1>foo</h1>\n              </div>\n            );\n          }\n        }\n\n        render() {\n          return <div>{this.renderContent()}</div>;\n        }\n      }\n\n      render(<Tester />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"login-container\"><h1>foo</h1></div></div>',\n      );\n      change1();\n      expect(container.innerHTML).toBe(\n        '<div><div><span>foo1</span><span>foo2</span><span>foo3</span><span>foo4</span></div></div>',\n      );\n      change1();\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"login-container\"><h1>foo</h1></div></div>',\n      );\n    });\n  });\n\n  describe('handling componentWillReceiveProps lifecycle event', () => {\n    it('should correctly handle setState within the lifecycle function', () => {\n      let renderCount = 0;\n      interface Comp1State {\n        foo: number;\n      }\n\n      class Comp1 extends Component<object, Comp1State> {\n        state: Comp1State;\n\n        constructor(props) {\n          super(props);\n          this.state = {\n            foo: 0,\n          };\n        }\n\n        componentWillReceiveProps() {\n          this.setState({ foo: 1 });\n        }\n\n        render() {\n          renderCount++;\n          return <div>{this.state.foo}</div>;\n        }\n      }\n\n      render(<Comp1 />, container);\n      expect(container.innerHTML).toBe('<div>0</div>');\n      render(<Comp1 />, container);\n      expect(container.innerHTML).toBe('<div>1</div>');\n      expect(renderCount).toBe(2);\n    });\n  });\n\n  it('mixing JSX components with non-JSX components', () => {\n    function Comp() {\n      return createElement('div', {});\n    }\n\n    function Comp2() {\n      return createElement('span', {});\n    }\n\n    function Comp3() {\n      return <div />;\n    }\n\n    render(\n      <div>\n        <Comp />\n      </div>,\n      container,\n    );\n    expect(container.innerHTML).toBe('<div><div></div></div>');\n    render(\n      <div>\n        <Comp2 />\n      </div>,\n      container,\n    );\n    expect(container.innerHTML).toBe('<div><span></span></div>');\n    render(\n      <span>\n        <Comp />\n      </span>,\n      container,\n    );\n    expect(container.innerHTML).toBe('<span><div></div></span>');\n    render(createElement('span', null, <Comp3 />), container);\n    expect(container.innerHTML).toBe('<span><div></div></span>');\n  });\n\n  describe('components should be able to use defaultProps', () => {\n    interface Comp1Props {\n      a?: string;\n      b?: string;\n      c?: string;\n    }\n\n    class Comp1 extends Component<Comp1Props> {\n      constructor(props) {\n        super(props);\n      }\n\n      static defaultProps = {\n        a: 'A',\n        b: 'B',\n      };\n\n      render() {\n        return (\n          <div className={this.props.a} id={this.props.b}>\n            Hello {this.props.c}!\n          </div>\n        );\n      }\n    }\n\n    class Comp2 extends Component<Comp1Props> {\n      constructor(props) {\n        super(props);\n      }\n\n      static defaultProps = {\n        a: 'aye',\n        b: 'bee',\n      };\n\n      render() {\n        return (\n          <div className={this.props.a} id={this.props.b}>\n            Hello {this.props.c}!\n          </div>\n        );\n      }\n    }\n\n    it('should mount component with defaultProps', () => {\n      render(<Comp1 c=\"C\" />, container);\n      expect(container.innerHTML).toBe('<div class=\"A\" id=\"B\">Hello C!</div>');\n    });\n\n    it('should mount child component with its defaultProps', () => {\n      const Parent = (props) => <div>{props.children.props.a}</div>;\n      render(\n        <Parent>\n          <Comp1 c=\"C\" />\n        </Parent>,\n        container,\n      );\n      expect(container.innerHTML).toBe('<div>A</div>');\n    });\n\n    it('should patch component with defaultProps', () => {\n      render(<Comp1 c=\"C\" />, container);\n      render(<Comp1 c=\"C2\" />, container);\n      expect(container.innerHTML).toBe('<div class=\"A\" id=\"B\">Hello C2!</div>');\n    });\n    it('should patch component with defaultProps #2', () => {\n      render(<Comp1 c=\"C\" />, container);\n      render(<Comp2 c=\"C1\" />, container);\n      expect(container.innerHTML).toBe(\n        '<div class=\"aye\" id=\"bee\">Hello C1!</div>',\n      );\n      render(<Comp1 c=\"C2\" />, container);\n      expect(container.innerHTML).toBe('<div class=\"A\" id=\"B\">Hello C2!</div>');\n    });\n\n    it('should as per React: Have childrens defaultProps set before children is mounted', () => {\n      let childrenPropertABeforeMount = 'A';\n      class Parent extends Component {\n        render() {\n          expect((this.props.children as any).props.a).toBe(\n            childrenPropertABeforeMount,\n          );\n\n          return <div>{this.props.children}</div>;\n        }\n      }\n\n      render(\n        <Parent>\n          <Comp1 />\n        </Parent>,\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"A\" id=\"B\">Hello !</div></div>',\n      );\n\n      childrenPropertABeforeMount = 'ABCD';\n\n      render(\n        <Parent>\n          <Comp1 a=\"ABCD\" />\n        </Parent>,\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"ABCD\" id=\"B\">Hello !</div></div>',\n      );\n    });\n  });\n\n  describe('when calling setState with a function', () => {\n    let reference;\n\n    interface Comp1State {\n      foo: string;\n    }\n\n    class Comp1 extends Component<object, Comp1State> {\n      state: Comp1State;\n\n      constructor(props) {\n        super(props);\n        this.state = {\n          foo: 'yar',\n        };\n        reference = this.update.bind(this);\n      }\n\n      update() {\n        this.setState(() => ({\n          foo: 'bar',\n        }));\n      }\n\n      render() {\n        return <div>{this.state.foo}</div>;\n      }\n    }\n\n    it('the state should update properly', (done) => {\n      render(<Comp1 />, container);\n      expect(container.innerHTML).toBe('<div>yar</div>');\n      reference();\n      setTimeout(() => {\n        expect(container.innerHTML).toBe('<div>bar</div>');\n        done();\n      }, 10);\n    });\n  });\n\n  describe('node change in updateComponent', () => {\n    it('Should not crash when invalid node returned - statefull', () => {\n      interface Comp1Props {\n        foo?: boolean;\n      }\n\n      class Comp1 extends Component<Comp1Props> {\n        constructor(props) {\n          super(props);\n        }\n\n        render() {\n          if (this.props.foo) {\n            return null;\n          }\n\n          return <div>rendered</div>;\n        }\n      }\n\n      render(<Comp1 />, container);\n      expect(container.innerHTML).toEqual('<div>rendered</div>');\n      render(<Comp1 foo={true} />, container);\n      expect(container.innerHTML).toEqual('');\n    });\n\n    it('Should not crash when invalid node returned - stateless', () => {\n      interface Comp1Props {\n        foo?: boolean;\n      }\n\n      const Comp1 = ({ foo }: Comp1Props) => {\n        if (foo) {\n          return null;\n        }\n\n        return <div>rendered</div>;\n      };\n\n      render(<Comp1 />, container);\n      expect(container.innerHTML).toEqual('<div>rendered</div>');\n      render(<Comp1 foo={true} />, container);\n      expect(container.innerHTML).toEqual('');\n    });\n  });\n\n  describe('Root handling issues #1', () => {\n    let div;\n\n    interface AState {\n      n: boolean;\n    }\n\n    class A extends Component<object, AState> {\n      state: AState;\n      private onClick: () => void;\n      constructor(props) {\n        super(props);\n        this.state = { n: false };\n\n        this.onClick = () => {\n          this.setState({ n: !this.state.n });\n        };\n      }\n\n      render() {\n        if (this.state.n) {\n          return (\n            <div ref={(dom) => (div = dom)} onClick={this.onClick}>\n              DIV\n            </div>\n          );\n        }\n        return <span onClick={this.onClick}>SPAN</span>;\n      }\n    }\n\n    class B extends Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n\n      render() {\n        return <A />;\n      }\n    }\n\n    interface TestState {\n      reverse: boolean;\n    }\n\n    class Test extends Component<object, TestState> {\n      state: TestState;\n      constructor(props) {\n        super(props);\n        this.state = {\n          reverse: false,\n        };\n      }\n\n      render() {\n        const children = [<B key=\"b\" />, <div key=\"a\">ROW</div>];\n        if (this.state.reverse) {\n          children.reverse();\n        }\n\n        return (\n          <div>\n            <button\n              onClick={() => {\n                this.setState({ reverse: !this.state.reverse });\n              }}\n            >\n              Swap Rows\n            </button>\n            <div>{children}</div>\n          </div>\n        );\n      }\n    }\n\n    // this test is to replicate https://jsfiddle.net/localvoid/r070sgrq/2/\n    it('should correct swap rows', () => {\n      render(<Test />, container);\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><span>SPAN</span><div>ROW</div></div></div>',\n      );\n      // click on \"SPAN\"\n      container.querySelector('span').click();\n      // \"SPAN\" should now be \"DIV\"\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>DIV</div><div>ROW</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>ROW</div><div>DIV</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>DIV</div><div>ROW</div></div></div>',\n      );\n      // click on \"DIV\"\n      div.click();\n      // \"DIV\" should now be \"SPAN\"\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><span>SPAN</span><div>ROW</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>ROW</div><span>SPAN</span></div></div>',\n      );\n    });\n  });\n\n  describe('Root handling issues #2', () => {\n    let div;\n\n    interface AState {\n      n: boolean;\n    }\n\n    class A extends Component<object, AState> {\n      state: AState;\n      private onClick: () => void;\n      constructor(props) {\n        super(props);\n        this.state = { n: false };\n\n        this.onClick = () => {\n          this.setState({ n: !this.state.n });\n        };\n      }\n\n      render() {\n        if (this.state.n) {\n          return (\n            <div ref={(dom) => (div = dom)} onClick={this.onClick}>\n              DIV\n            </div>\n          );\n        }\n        return <span onClick={this.onClick}>SPAN</span>;\n      }\n    }\n\n    function F() {\n      return <A />;\n    }\n\n    class B extends Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n\n      render() {\n        return <F />;\n      }\n    }\n\n    interface TestState {\n      reverse: boolean;\n    }\n\n    class Test extends Component<object, TestState> {\n      state: TestState;\n      constructor(props) {\n        super(props);\n        this.state = {\n          reverse: false,\n        };\n      }\n\n      render() {\n        const children = [<B key=\"b\" />, <div key=\"a\">ROW</div>];\n        if (this.state.reverse) {\n          children.reverse();\n        }\n\n        return (\n          <div>\n            <button\n              onClick={() => {\n                this.setState({ reverse: !this.state.reverse });\n              }}\n            >\n              Swap Rows\n            </button>\n            <div>{children}</div>\n          </div>\n        );\n      }\n    }\n\n    // this test is to replicate https://jsfiddle.net/localvoid/r070sgrq/2/\n    it('should correct swap rows', () => {\n      render(<Test />, container);\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><span>SPAN</span><div>ROW</div></div></div>',\n      );\n      // click on \"SPAN\"\n      container.querySelector('span').click();\n      // \"SPAN\" should now be \"DIV\"\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>DIV</div><div>ROW</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>ROW</div><div>DIV</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>DIV</div><div>ROW</div></div></div>',\n      );\n      // click on \"DIV\"\n      div.click();\n      // \"DIV\" should now be \"SPAN\"\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><span>SPAN</span><div>ROW</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>ROW</div><span>SPAN</span></div></div>',\n      );\n    });\n  });\n\n  describe('Root handling issues #3', () => {\n    let div;\n\n    interface AState {\n      n: boolean;\n    }\n\n    class A extends Component<object, AState> {\n      state: AState;\n      private onClick: () => void;\n      constructor(props) {\n        super(props);\n        this.state = { n: false };\n\n        this.onClick = () => {\n          this.setState({ n: !this.state.n });\n        };\n      }\n\n      render() {\n        if (this.state.n) {\n          return (\n            <div ref={(dom) => (div = dom)} onClick={this.onClick}>\n              DIV\n            </div>\n          );\n        }\n        return <span onClick={this.onClick}>SPAN</span>;\n      }\n    }\n\n    function F() {\n      return <A />;\n    }\n\n    function B() {\n      return <F onComponentShouldUpdate={() => false} />;\n    }\n\n    interface TestState {\n      reverse: boolean;\n    }\n\n    class Test extends Component<object, TestState> {\n      state: TestState;\n      constructor(props) {\n        super(props);\n        this.state = {\n          reverse: false,\n        };\n      }\n\n      render() {\n        const children = [\n          <B key=\"b\" onComponentShouldUpdate={() => false} />,\n          <div key=\"a\">ROW</div>,\n        ];\n        if (this.state.reverse) {\n          children.reverse();\n        }\n\n        return (\n          <div>\n            <button\n              onClick={() => {\n                this.setState({ reverse: !this.state.reverse });\n              }}\n            >\n              Swap Rows\n            </button>\n            <div>{children}</div>\n          </div>\n        );\n      }\n    }\n\n    // this test is to replicate https://jsfiddle.net/localvoid/r070sgrq/2/\n    it('should correct swap rows', () => {\n      render(<Test />, container);\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><span>SPAN</span><div>ROW</div></div></div>',\n      );\n      // click on \"SPAN\"\n      container.querySelector('span').click();\n      // \"SPAN\" should now be \"DIV\"\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>DIV</div><div>ROW</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>ROW</div><div>DIV</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>DIV</div><div>ROW</div></div></div>',\n      );\n      // click on \"DIV\"\n      div.click();\n\n      // \"DIV\" should now be \"SPAN\"\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><span>SPAN</span><div>ROW</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>ROW</div><span>SPAN</span></div></div>',\n      );\n\n      render(null, container);\n    });\n  });\n\n  describe('Root handling issues #4', () => {\n    interface AState {\n      n: boolean;\n    }\n\n    class A extends Component<object, AState> {\n      state: AState;\n      private onClick: () => void;\n      constructor(props) {\n        super(props);\n        this.state = { n: false };\n\n        this.onClick = () => {\n          this.setState({ n: !this.state.n });\n        };\n      }\n\n      render() {\n        if (this.state.n) {\n          return <div onClick={this.onClick}>DIV</div>;\n        }\n        return <span onClick={this.onClick}>SPAN</span>;\n      }\n    }\n\n    class B extends Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n\n      render() {\n        return this.props.children;\n      }\n    }\n\n    interface TestState {\n      reverse: boolean;\n    }\n\n    class Test extends Component<object, TestState> {\n      state: TestState;\n\n      constructor(props) {\n        super(props);\n        this.state = {\n          reverse: false,\n        };\n      }\n\n      render() {\n        const children = [\n          <B key=\"b\">\n            <A />\n          </B>,\n          <div key=\"a\">A</div>,\n        ];\n        if (this.state.reverse) {\n          children.reverse();\n        }\n\n        return (\n          <div>\n            <button\n              onClick={() => {\n                this.setState({ reverse: !this.state.reverse });\n              }}\n            >\n              Swap Rows\n            </button>\n            <div>{children}</div>\n            <div>{children}</div>\n          </div>\n        );\n      }\n    }\n\n    it('should correct swap rows', () => {\n      render(<Test />, container);\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><span>SPAN</span><div>A</div></div><div><span>SPAN</span><div>A</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>A</div><span>SPAN</span></div><div><div>A</div><span>SPAN</span></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><span>SPAN</span><div>A</div></div><div><span>SPAN</span><div>A</div></div></div>',\n      );\n    });\n  });\n\n  describe('Root handling issues #5', () => {\n    interface AState {\n      n: boolean;\n    }\n\n    class A extends Component<object, AState> {\n      state: AState;\n      private onClick: () => void;\n\n      constructor(props) {\n        super(props);\n        this.state = { n: false };\n\n        this.onClick = () => {\n          this.setState({ n: !this.state.n });\n        };\n      }\n\n      render() {\n        if (this.state.n) {\n          return <div onClick={this.onClick}>DIV</div>;\n        }\n        return <span onClick={this.onClick}>SPAN</span>;\n      }\n    }\n\n    const hoisted = <A />;\n\n    class B extends Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n\n      render() {\n        return hoisted;\n      }\n    }\n\n    interface TestState {\n      reverse: boolean;\n    }\n\n    class Test extends Component<object, TestState> {\n      state: TestState;\n      constructor(props) {\n        super(props);\n        this.state = {\n          reverse: false,\n        };\n      }\n\n      render() {\n        const children = [<B key=\"b\" />, <div key=\"a\">A</div>];\n        if (this.state.reverse) {\n          children.reverse();\n        }\n        Object.freeze(children);\n\n        return (\n          <div>\n            <button\n              onClick={() => {\n                this.setState({ reverse: !this.state.reverse });\n              }}\n            >\n              Swap Rows\n            </button>\n            <div>{children}</div>\n            <div>{children}</div>\n          </div>\n        );\n      }\n    }\n\n    it('should correct swap rows', () => {\n      render(<Test />, container);\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><span>SPAN</span><div>A</div></div><div><span>SPAN</span><div>A</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>A</div><span>SPAN</span></div><div><div>A</div><span>SPAN</span></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><span>SPAN</span><div>A</div></div><div><span>SPAN</span><div>A</div></div></div>',\n      );\n    });\n  });\n\n  describe('Root handling issues #6', () => {\n    let i;\n\n    beforeEach(function () {\n      i = 1;\n    });\n\n    class B extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      shouldComponentUpdate() {\n        return false;\n      }\n\n      render() {\n        return <div>{i}</div>;\n      }\n    }\n\n    class Test extends Component {\n      render() {\n        return (\n          <div>\n            <button\n              onClick={() => {\n                i++;\n                this.setState({});\n              }}\n            >\n              Replace\n            </button>\n            <div>\n              <B key={i} />\n            </div>\n          </div>\n        );\n      }\n    }\n\n    it('should replace keyed component if key changes', () => {\n      render(<Test />, container);\n      expect(container.innerHTML).toEqual(\n        '<div><button>Replace</button><div><div>1</div></div></div>',\n      );\n      // click \"Replace\"\n      container.querySelector('button').click();\n      expect(container.innerHTML).toEqual(\n        '<div><button>Replace</button><div><div>2</div></div></div>',\n      );\n    });\n  });\n\n  describe('Cloned children issues #1', () => {\n    interface TestState {\n      reverse: boolean;\n    }\n\n    class Test extends Component<object, TestState> {\n      state: TestState;\n\n      constructor(props) {\n        super(props);\n        this.state = {\n          reverse: false,\n        };\n      }\n\n      render() {\n        const a = <div key=\"b\">B</div>;\n        const b = <div key=\"a\">A</div>;\n\n        return (\n          <div>\n            <button\n              onClick={() => {\n                this.setState({ reverse: !this.state.reverse });\n              }}\n            >\n              Swap Rows\n            </button>\n            <div>{this.state.reverse ? [a, b].reverse() : [a, b]}</div>\n            <div>{this.state.reverse ? [a, b].reverse() : [a, b]}</div>\n          </div>\n        );\n      }\n    }\n\n    // this test is to replicate https://jsfiddle.net/localvoid/fmznjwxv/\n    it('should correct swap rows', () => {\n      render(<Test />, container);\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>B</div><div>A</div></div><div><div>B</div><div>A</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n    });\n  });\n  describe('Cloned children issues #2', () => {\n    interface TestState {\n      reverse: boolean;\n    }\n\n    class Test extends Component<object, TestState> {\n      state: TestState;\n\n      constructor(props) {\n        super(props);\n        this.state = {\n          reverse: false,\n        };\n      }\n\n      render() {\n        const children = [<div key=\"b\">B</div>, <div key=\"a\">A</div>];\n        if (this.state.reverse) {\n          children.reverse();\n        }\n\n        return (\n          <div>\n            <button\n              onClick={() => {\n                this.setState({ reverse: !this.state.reverse });\n              }}\n            >\n              Swap Rows\n            </button>\n            <div>{children}</div>\n            <div>{children}</div>\n          </div>\n        );\n      }\n    }\n\n    // this test is to replicate https://jsfiddle.net/localvoid/fmznjwxv/\n    it('should correct swap rows', () => {\n      render(<Test />, container);\n      expect(container.innerHTML).toEqual(\n        '<div><button>Swap Rows</button><div><div>B</div><div>A</div></div><div><div>B</div><div>A</div></div></div>',\n      );\n      // click \"SWAP ROWS\"\n      container.querySelector('button').click();\n    });\n  });\n\n  describe('Asynchronous setStates', () => {\n    it('Should not fail when parent component calls setState on unmounting children', (done) => {\n      interface ParentProps {\n        toggle: boolean;\n      }\n\n      interface ParentState {\n        text: string;\n      }\n\n      class Parent extends Component<ParentProps, ParentState> {\n        state: ParentState;\n\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            text: 'bar',\n          };\n\n          this.changeState = this.changeState.bind(this);\n        }\n\n        changeState() {\n          this.setState({\n            text: 'foo',\n          });\n        }\n\n        render() {\n          return (\n            <div>\n              <span>{this.state.text}</span>\n              {this.props.toggle ? (\n                [<Tester toggle={this.props.toggle} call={this.changeState} />]\n              ) : (\n                <span style={this.props.toggle ? { color: 'blue' } : null}>\n                  tester\n                </span>\n              )}\n            </div>\n          );\n        }\n      }\n\n      class Tester extends Component<{ call: () => void; toggle: boolean }> {\n        constructor(props) {\n          super(props);\n        }\n\n        componentWillUnmount() {\n          // parent will do setState\n          this.props.call();\n        }\n\n        render() {\n          return (\n            <div>\n              <span style={this.props.toggle ? { color: 'blue' } : null}>\n                foo\n              </span>\n            </div>\n          );\n        }\n      }\n\n      render(<Parent toggle={true} />, container);\n\n      expect(container.innerHTML).toEqual(\n        '<div><span>bar</span><div><span style=\"color: blue;\">foo</span></div></div>',\n      );\n\n      render(<Parent toggle={false} />, container);\n\n      setTimeout(() => {\n        done();\n      }, 40);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/components3.spec.tsx",
    "content": "import { Component, InfernoChild, render, rerender } from 'inferno';\n\ndescribe('Components 3 (TSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    document.body.removeChild(container);\n  });\n\n  describe('should render a repeating counter component with component children', () => {\n    interface ValueProps {\n      value: number;\n    }\n\n    class Value extends Component<ValueProps> {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return <div>{this.props.value}</div>;\n      }\n    }\n\n    interface RepeaterProps {\n      value: number;\n    }\n\n    class Repeater extends Component<RepeaterProps> {\n      render() {\n        const children: InfernoChild[] = [];\n        for (let i = 0; i < 3; i++) {\n          children.push(<Value key={i} value={this.props.value} />);\n        }\n\n        return <div>{children}</div>;\n      }\n    }\n\n    it('should correctly render as values increase', () => {\n      let value = 0;\n\n      render(<Repeater value={value} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>0</div><div>0</div><div>0</div></div>',\n      );\n\n      value++;\n      render(<Repeater value={value} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>1</div><div>1</div><div>1</div></div>',\n      );\n\n      value++;\n      render(<Repeater value={value} />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>2</div><div>2</div><div>2</div></div>',\n      );\n    });\n  });\n\n  describe('should render a component with component children as the only child', () => {\n    class Jaska extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return (\n          <div>\n            <h1>Okdokfwoe</h1>\n            <p>odkodwq</p>\n          </div>\n        );\n      }\n    }\n\n    class Container extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return <div>{this.props.children}</div>;\n      }\n    }\n\n    class TestingProps extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return (\n          <div>\n            <Container>\n              <Jaska />\n            </Container>\n          </div>\n        );\n      }\n    }\n\n    it('should correctly render', () => {\n      render(<TestingProps />, container);\n      expect(container.innerHTML).toBe(\n        '<div><div><div><h1>Okdokfwoe</h1><p>odkodwq</p></div></div></div>',\n      );\n    });\n  });\n\n  describe('should render a component with with mapped text nodes', () => {\n    interface MyComponent99Props {\n      isok: boolean;\n    }\n\n    interface MyComponent98State {\n      isok: boolean;\n    }\n\n    class MyComponent98 extends Component<object, MyComponent98State> {\n      state: MyComponent98State;\n\n      constructor(props) {\n        super(props);\n        this.state = {\n          isok: false,\n        };\n      }\n\n      componentDidMount() {\n        this.setState({ isok: true });\n      }\n\n      render() {\n        return <MyComponent99 isok={this.state.isok} />;\n      }\n    }\n\n    class MyComponent99 extends Component<MyComponent99Props> {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return (\n          <div>\n            isok=\n            {this.props.isok ? 'true' : 'false'}\n            <div>\n              {this.props.isok &&\n                ['a', 'b'].map((x) => {\n                  return <span>{x}</span>;\n                })}\n            </div>\n          </div>\n        );\n      }\n    }\n\n    it('should correctly render', () => {\n      render(<MyComponent98 />, container);\n\n      expect(container.innerHTML).toBe('<div>isok=false<div></div></div>');\n\n      rerender();\n\n      expect(container.innerHTML).toBe(\n        '<div>isok=true<div><span>a</span><span>b</span></div></div>',\n      );\n    });\n  });\n\n  describe('should render a component with conditional boolean text nodes', () => {\n    interface MyComponent98State {\n      isok: boolean;\n    }\n\n    interface MyComponent99Props {\n      isok: boolean;\n    }\n\n    class MyComponent98 extends Component<object, MyComponent98State> {\n      state: MyComponent98State;\n\n      constructor(props) {\n        super(props);\n        this.state = {\n          isok: false,\n        };\n      }\n\n      componentDidMount() {\n        this.setState({ isok: true });\n      }\n\n      render() {\n        return <MyComponent99 isok={this.state.isok} />;\n      }\n    }\n\n    class MyComponent99 extends Component<MyComponent99Props> {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        const z = function (v) {\n          if (v) {\n            return <span>a</span>;\n          } else {\n            return <span>b</span>;\n          }\n        };\n\n        return (\n          <div>\n            <div>{z(this.props.isok)}</div>\n          </div>\n        );\n      }\n    }\n\n    it('should correctly render', (done) => {\n      render(<MyComponent98 />, container);\n      setTimeout(() => {\n        expect(container.innerHTML).toBe(\n          '<div><div><span>a</span></div></div>',\n        );\n        done();\n      }, 25);\n    });\n  });\n\n  const StatelessComponent2 = (props) => <div>{props.name}</div>;\n\n  it('should render stateless component', () => {\n    render(<StatelessComponent2 name=\"A\" />, container);\n    expect(container.textContent).toBe('A');\n  });\n\n  it('should unmount stateless component', function () {\n    render(<StatelessComponent2 name=\"A\" />, container);\n    expect(container.textContent).toBe('A');\n\n    render(null, container);\n    expect(container.textContent).toBe('');\n  });\n\n  it('should support module pattern components', function () {\n    function Child({ test }) {\n      return <div>{test}</div>;\n    }\n\n    render(<Child test=\"test\" />, container);\n\n    expect(container.textContent).toBe('test');\n  });\n\n  describe('should render a component with a conditional list that changes upon toggle', () => {\n    class BuggyRender extends Component<object, { empty: boolean }> {\n      state: { empty: boolean };\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          empty: true,\n        };\n\n        this.toggle = this.toggle.bind(this);\n      }\n\n      toggle() {\n        this.setState({\n          empty: !this.state.empty,\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            <button onClick={this.toggle}>Empty</button>\n            <ul>\n              {(() => {\n                if (this.state.empty === true) {\n                  return <li>No cars!</li>;\n                } else {\n                  return ['BMW', 'Volvo', 'Saab'].map(function (car) {\n                    return <li>{car}</li>;\n                  });\n                }\n              })()}\n            </ul>\n          </div>\n        );\n      }\n    }\n\n    it('should correctly render', () => {\n      render(<BuggyRender />, container);\n      expect(container.innerHTML).toBe(\n        '<div><button>Empty</button><ul><li>No cars!</li></ul></div>',\n      );\n    });\n\n    it('should handle update upon click', () => {\n      render(<BuggyRender />, container);\n      const buttons = container.querySelectorAll('button');\n\n      for (const button of buttons) {\n        button.click();\n      }\n\n      expect(container.innerHTML).toBe(\n        '<div><button>Empty</button><ul><li>BMW</li><li>Volvo</li><li>Saab</li></ul></div>',\n      );\n    });\n  });\n\n  describe('should render a component with a list that instantly changes', () => {\n    interface ChangeChildrenCountState {\n      list: string[];\n    }\n    class ChangeChildrenCount extends Component<\n      object,\n      ChangeChildrenCountState\n    > {\n      state: ChangeChildrenCountState;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          list: ['1', '2', '3', '4'],\n        };\n\n        this.handleClick = this.handleClick.bind(this);\n      }\n\n      handleClick() {\n        this.setState({\n          list: ['1'],\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            <button onClick={this.handleClick}>1</button>\n            {this.state.list.map(function (_x, i) {\n              return <div>{i}</div>;\n            })}\n          </div>\n        );\n      }\n    }\n\n    it('should correctly render', () => {\n      render(<ChangeChildrenCount />, container);\n      expect(container.innerHTML).toBe(\n        '<div><button>1</button><div>0</div><div>1</div><div>2</div><div>3</div></div>',\n      );\n    });\n\n    it('should handle update upon click', (done) => {\n      render(<ChangeChildrenCount />, container);\n      const buttons = container.querySelectorAll('button');\n\n      for (const button of buttons) {\n        button.click();\n      }\n\n      setTimeout(() => {\n        expect(container.innerHTML).toBe(\n          '<div><button>1</button><div>0</div></div>',\n        );\n        done();\n      }, 10);\n    });\n  });\n\n  describe('should render a stateless component with context', () => {\n    const StatelessComponent3 = ({ value }, { fortyTwo }) => (\n      <p>\n        {value}-{fortyTwo || 'ERROR'}\n      </p>\n    );\n\n    interface FirstState {\n      counter: number;\n    }\n\n    class First extends Component<object, FirstState> {\n      state: FirstState;\n\n      constructor(props, context) {\n        super(props, context);\n\n        this.state = {\n          counter: 0,\n        };\n\n        this._onClick = this._onClick.bind(this);\n      }\n\n      _onClick() {\n        this.setState({\n          counter: 1,\n        });\n      }\n\n      getChildContext() {\n        return {\n          fortyTwo: 42,\n        };\n      }\n\n      render() {\n        return (\n          <div>\n            <button onClick={this._onClick}>\n              Increase! {this.state.counter}\n            </button>\n            <StatelessComponent3 value={this.state.counter} />\n          </div>\n        );\n      }\n    }\n\n    it('should correctly render', () => {\n      render(<First />, container);\n      expect(container.innerHTML).toBe(\n        '<div><button>Increase! 0</button><p>0-42</p></div>',\n      );\n    });\n\n    it('should handle update upon click', (done) => {\n      render(<First />, container);\n      const buttons = container.querySelectorAll('button');\n\n      for (const button of buttons) {\n        button.click();\n      }\n\n      setTimeout(() => {\n        expect(container.innerHTML).toBe(\n          '<div><button>Increase! 1</button><p>1-42</p></div>',\n        );\n        done();\n      }, 10);\n    });\n  });\n\n  describe('should render a conditional stateless component', () => {\n    const StatelessComponent4 = ({ value }) => <p>{value}</p>;\n\n    interface FirstState {\n      counter: number;\n    }\n\n    class First extends Component<object, FirstState> {\n      state: FirstState;\n      private condition: boolean;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          counter: 0,\n        };\n\n        this.condition = true;\n        this._onClick = this._onClick.bind(this);\n      }\n\n      _onClick() {\n        this.setState({\n          counter: 1,\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            <button onClick={this._onClick}>\n              Increase! {this.state.counter}\n            </button>\n            {this.condition ? (\n              <StatelessComponent4 value={this.state.counter} />\n            ) : null}\n          </div>\n        );\n      }\n    }\n\n    it('should correctly render', () => {\n      render(<First />, container);\n      expect(container.innerHTML).toBe(\n        '<div><button>Increase! 0</button><p>0</p></div>',\n      );\n    });\n\n    it('should handle update upon click', (done) => {\n      render(<First />, container);\n      const buttons = container.querySelectorAll('button');\n\n      for (const button of buttons) {\n        button.click();\n      }\n\n      setTimeout(() => {\n        expect(container.innerHTML).toBe(\n          '<div><button>Increase! 1</button><p>1</p></div>',\n        );\n        done();\n      }, 10);\n    });\n  });\n\n  describe('should render stateless component correctly when changing states', () => {\n    let firstDiv, secondDiv;\n\n    beforeEach(function () {\n      firstDiv = document.createElement('div');\n      secondDiv = document.createElement('div');\n\n      container.appendChild(firstDiv);\n      container.appendChild(secondDiv);\n    });\n\n    afterEach(function () {\n      render(null, firstDiv);\n      render(null, secondDiv);\n    });\n\n    const StatelessComponent = ({ value }) => <p>{value}</p>;\n\n    interface FirstState {\n      counter: number;\n    }\n\n    class First extends Component<{ name: string }, FirstState> {\n      state: FirstState;\n      private condition: boolean;\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          counter: 0,\n        };\n\n        this.condition = true;\n        this._onClick = this._onClick.bind(this);\n      }\n\n      _onClick() {\n        this.setState({\n          counter: 1,\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            <button onClick={this._onClick}>\n              {this.props.name} {this.state.counter}\n            </button>\n            {this.condition ? (\n              <StatelessComponent value={this.state.counter} />\n            ) : null}\n          </div>\n        );\n      }\n    }\n\n    it('should correctly render', () => {\n      render(<First name=\"guy1\" />, firstDiv);\n      render(<First name=\"guy2\" />, secondDiv);\n\n      expect(container.innerHTML).toBe(\n        '<div><div><button>guy1 0</button><p>0</p></div></div><div><div><button>guy2 0</button><p>0</p></div></div>',\n      );\n    });\n\n    it('should handle update when changing first component', (done) => {\n      render(<First name=\"guy1\" />, firstDiv);\n      render(<First name=\"guy2\" />, secondDiv);\n\n      const buttons = firstDiv.querySelectorAll('button');\n      for (const button of buttons) {\n        button.click();\n      }\n\n      setTimeout(() => {\n        expect(container.innerHTML).toBe(\n          '<div><div><button>guy1 1</button><p>1</p></div></div><div><div><button>guy2 0</button><p>0</p></div></div>',\n        );\n        done();\n      }, 10);\n    });\n\n    it('should handle update when changing second component', (done) => {\n      render(<First name=\"guy1\" />, firstDiv);\n      render(<First name=\"guy2\" />, secondDiv);\n\n      const buttons = secondDiv.querySelectorAll('button');\n      for (const button of buttons) {\n        button.click();\n      }\n\n      setTimeout(() => {\n        expect(container.innerHTML).toBe(\n          '<div><div><button>guy1 0</button><p>0</p></div></div><div><div><button>guy2 1</button><p>1</p></div></div>',\n        );\n        done();\n      }, 10);\n    });\n  });\n\n  describe('updating child should not cause rendering parent to fail', () => {\n    it('should render parent correctly after child changes', (done) => {\n      let updateParent, updateChild;\n\n      interface ParentState {\n        x: boolean;\n      }\n\n      class Parent extends Component<object, ParentState> {\n        state: ParentState;\n\n        constructor(props) {\n          super(props);\n          this.state = { x: false };\n\n          updateParent = () => {\n            this.setState({ x: true });\n          };\n        }\n\n        render() {\n          return (\n            <div>\n              <p>parent</p>\n              {!this.state.x ? <ChildA /> : <ChildB />}\n            </div>\n          );\n        }\n      }\n\n      class ChildB extends Component {\n        constructor(props) {\n          super(props);\n        }\n\n        render() {\n          return <div>Y</div>;\n        }\n      }\n\n      interface ChildAState {\n        z: boolean;\n      }\n\n      class ChildA extends Component<object, ChildAState> {\n        state: ChildAState;\n\n        constructor(props) {\n          super(props);\n          this.state = { z: false };\n\n          updateChild = () => {\n            this.setState({ z: true });\n          };\n        }\n\n        render() {\n          if (!this.state.z) {\n            return <div>A</div>;\n          }\n          return <SubChild />;\n        }\n      }\n\n      class SubChild extends Component {\n        constructor(props) {\n          super(props);\n        }\n\n        render() {\n          return <div>B</div>;\n        }\n      }\n\n      render(<Parent />, container);\n      expect(container.innerHTML).toBe('<div><p>parent</p><div>A</div></div>');\n      updateChild();\n      setTimeout(() => {\n        expect(container.innerHTML).toBe(\n          '<div><p>parent</p><div>B</div></div>',\n        );\n        updateParent();\n        setTimeout(() => {\n          expect(container.innerHTML).toBe(\n            '<div><p>parent</p><div>Y</div></div>',\n          );\n          done();\n        }, 10);\n      }, 10);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/createElement.fragment.spec.ts",
    "content": "import {\n  Component,\n  createFragment,\n  createPortal,\n  Fragment,\n  render,\n  rerender,\n  VNode,\n} from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport { ChildFlags } from 'inferno-vnode-flags';\n\ndescribe('CreateElement (non-JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('Fragments', () => {\n    it('Should render and unmount fragment', () => {\n      const Example = class Example extends Component {\n        render() {\n          return createFragment(\n            [\n              createElement('div', null, 'First'),\n              createElement('div', null, 'second'),\n            ],\n            ChildFlags.HasNonKeyedChildren,\n          );\n        }\n      };\n\n      render(createElement(Example, null), container);\n\n      expect(container.innerHTML).toBe('<div>First</div><div>second</div>');\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should render nested fragment', () => {\n      const Example = class Example extends Component {\n        render() {\n          return createFragment(\n            [\n              createElement('div', null, 'First'),\n              createFragment(\n                [\n                  createElement('div', null, 'Sub1'),\n                  createElement('div', null, 'Sub2'),\n                ],\n                ChildFlags.HasNonKeyedChildren,\n              ),\n              createElement('div', null, 'second'),\n            ],\n            ChildFlags.HasNonKeyedChildren,\n          );\n        }\n      };\n\n      render(createElement(Example, null), container);\n\n      expect(container.innerHTML).toBe(\n        '<div>First</div><div>Sub1</div><div>Sub2</div><div>second</div>',\n      );\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should be to replace component with fragment with another component', () => {\n      const Example = class Example extends Component {\n        render() {\n          return createFragment(\n            [\n              createElement('div', null, 'First'),\n              createFragment(\n                [\n                  createElement('div', null, 'Sub1'),\n                  createElement('div', null, 'Sub2'),\n                ],\n                ChildFlags.HasNonKeyedChildren,\n              ),\n              createElement('div', null, 'second'),\n            ],\n            ChildFlags.HasNonKeyedChildren,\n          );\n        }\n      };\n\n      function FunctionalComp() {\n        return createFragment(\n          [createElement('div', null, 'Functional')],\n          ChildFlags.HasNonKeyedChildren,\n        );\n      }\n\n      render(createElement(Example, null), container);\n\n      expect(container.innerHTML).toBe(\n        '<div>First</div><div>Sub1</div><div>Sub2</div><div>second</div>',\n      );\n\n      render(createElement(FunctionalComp, null), container);\n\n      expect(container.innerHTML).toBe('<div>Functional</div>');\n\n      render(createElement(Example, null), container);\n\n      expect(container.innerHTML).toBe(\n        '<div>First</div><div>Sub1</div><div>Sub2</div><div>second</div>',\n      );\n\n      render(createElement(FunctionalComp, null), container);\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should be possible to move fragments', () => {\n      const fragmentA = () =>\n        createFragment(\n          [\n            createElement('div', { id: 'a1' }, 'A1'),\n            createElement('div', null, 'A2'),\n          ],\n          ChildFlags.HasNonKeyedChildren,\n          'A',\n        );\n\n      const fragmentB = () =>\n        createFragment(\n          [createElement('div', { id: 'b1' }, 'B1')],\n          ChildFlags.HasNonKeyedChildren,\n          'B',\n        );\n\n      const fragmentC = () =>\n        createFragment(\n          [\n            createElement('div', { id: 'c1' }, 'C1'),\n            createElement('div', null, 'C2'),\n            createElement('div', null, 'C3'),\n          ],\n          ChildFlags.HasNonKeyedChildren,\n          'C',\n        );\n\n      render(\n        createElement('div', null, fragmentA(), fragmentB(), fragmentC()),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<div><div id=\"a1\">A1</div><div>A2</div><div id=\"b1\">B1</div><div id=\"c1\">C1</div><div>C2</div><div>C3</div></div>',\n      );\n\n      const A1 = container.querySelector('#a1');\n      const B1 = container.querySelector('#b1');\n      const C1 = container.querySelector('#c1');\n\n      // Switch order\n      render(\n        createElement('div', null, fragmentC(), fragmentA(), fragmentB()),\n        container,\n      );\n\n      // Verify dom has changed and nodes are the same\n      expect(container.innerHTML).toBe(\n        '<div><div id=\"c1\">C1</div><div>C2</div><div>C3</div><div id=\"a1\">A1</div><div>A2</div><div id=\"b1\">B1</div></div>',\n      );\n\n      expect(container.querySelector('#a1')).toBe(A1);\n      expect(container.querySelector('#b1')).toBe(B1);\n      expect(container.querySelector('#c1')).toBe(C1);\n\n      // Switch order again\n      render(createElement('div', null, fragmentB(), fragmentC()), container);\n\n      // Verify dom has changed and nodes are the same\n      expect(container.innerHTML).toBe(\n        '<div><div id=\"b1\">B1</div><div id=\"c1\">C1</div><div>C2</div><div>C3</div></div>',\n      );\n\n      expect(container.querySelector('#a1')).toBe(null);\n      expect(container.querySelector('#b1')).toBe(B1);\n      expect(container.querySelector('#c1')).toBe(C1);\n    });\n\n    it('Should clone fragment children if they are passed as reference', () => {\n      const fragmentA = createFragment(\n        [\n          createElement('div', { id: 'a1' }, 'A1'),\n          createElement('div', null, 'A2'),\n        ],\n        ChildFlags.HasNonKeyedChildren,\n        'A',\n      );\n      const fragmentB = createFragment(\n        [createElement('div', { id: 'b1' }, 'B1')],\n        ChildFlags.HasNonKeyedChildren,\n        'B',\n      );\n      const fragmentC = createFragment(\n        [\n          createElement('div', { id: 'c1' }, 'C1'),\n          createElement('div', null, 'C2'),\n          createElement('div', null, 'C3'),\n        ],\n        ChildFlags.HasNonKeyedChildren,\n        'C',\n      );\n\n      const content = [fragmentC];\n\n      function SFC() {\n        return createElement(\n          Fragment,\n          null,\n          createElement('span', null, '1'),\n          createElement(Fragment, null, content),\n          createElement('span', null, '2'),\n        );\n      }\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          fragmentA,\n          createElement(SFC, { key: 'sfc' }),\n          fragmentB,\n          fragmentC,\n        ),\n        container,\n      );\n\n      const FragmentAHtml = '<div id=\"a1\">A1</div><div>A2</div>';\n      const FragmentBHtml = '<div id=\"b1\">B1</div>';\n      const FragmentCHtml = '<div id=\"c1\">C1</div><div>C2</div><div>C3</div>';\n      const SFCHtml = '<span>1</span>' + FragmentCHtml + '<span>2</span>';\n\n      expect(container.innerHTML).toBe(\n        FragmentAHtml + SFCHtml + FragmentBHtml + FragmentCHtml,\n      );\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should be possible to move component with fragment root', () => {\n      const fragmentA = createFragment(\n        [\n          createElement('div', { id: 'a1' }, 'A1'),\n          createElement('div', null, 'A2'),\n        ],\n        ChildFlags.HasNonKeyedChildren,\n        'A',\n      );\n      const fragmentB = createFragment(\n        [createElement('div', { id: 'b1' }, 'B1')],\n        ChildFlags.HasNonKeyedChildren,\n        'B',\n      );\n      const fragmentC = createFragment(\n        [\n          createElement('div', { id: 'c1' }, 'C1'),\n          createElement('div', null, 'C2'),\n          createElement('div', null, 'C3'),\n        ],\n        ChildFlags.HasNonKeyedChildren,\n        'C',\n      );\n\n      const content = [fragmentC];\n\n      function SFC() {\n        return createElement(\n          Fragment,\n          null,\n          createElement('span', null, '1'),\n          createElement(Fragment, null, content),\n          createElement('span', null, '2'),\n        );\n      }\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          fragmentA,\n          createElement(SFC, { key: 'sfc' }),\n          fragmentB,\n          fragmentC,\n        ),\n        container,\n      );\n\n      const FragmentAHtml = '<div id=\"a1\">A1</div><div>A2</div>';\n      const FragmentBHtml = '<div id=\"b1\">B1</div>';\n      const FragmentCHtml = '<div id=\"c1\">C1</div><div>C2</div><div>C3</div>';\n      const SFCHtml = '<span>1</span>' + FragmentCHtml + '<span>2</span>';\n\n      expect(container.innerHTML).toBe(\n        FragmentAHtml + SFCHtml + FragmentBHtml + FragmentCHtml,\n      );\n\n      // Switch order\n      render(\n        createElement(\n          Fragment,\n          null,\n          fragmentA,\n          fragmentC,\n          createElement(SFC, { key: 'sfc' }),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(FragmentAHtml + FragmentCHtml + SFCHtml);\n\n      // Switch order again\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement('div', { key: '1' }, '1'),\n          createElement(SFC, { key: 'sfc' }),\n          fragmentA,\n          fragmentC,\n          createElement('div', { key: '1' }, '2'),\n        ),\n        container,\n      );\n\n      // Verify dom has changed and nodes are the same\n      expect(container.innerHTML).toBe(\n        '<div>1</div>' +\n          SFCHtml +\n          FragmentAHtml +\n          FragmentCHtml +\n          '<div>2</div>',\n      );\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should be possible to move component with fragment root #2', () => {\n      const fragmentA = createFragment(\n        [\n          createElement('div', { id: 'a1' }, 'A1'),\n          createElement('div', null, 'A2'),\n        ],\n        ChildFlags.HasNonKeyedChildren,\n        'A',\n      );\n      const fragmentB = createFragment(\n        [createElement('div', { id: 'b1' }, 'B1')],\n        ChildFlags.HasNonKeyedChildren,\n        'B',\n      );\n      const fragmentC = createFragment(\n        [\n          createElement('div', { id: 'c1' }, 'C1'),\n          createElement('div', null, 'C2'),\n          createElement('div', null, 'C3'),\n        ],\n        ChildFlags.HasNonKeyedChildren,\n        'C',\n      );\n\n      const content = [fragmentC];\n\n      function SFC() {\n        return createElement(\n          Fragment,\n          null,\n          createElement('span', null, '1'),\n          createElement(Fragment, null, content),\n          createElement('span', null, '2'),\n        );\n      }\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          fragmentA,\n          createElement(SFC, { key: 'sfc1' }),\n          fragmentB,\n          createElement(SFC, { key: 'sfc2' }),\n          fragmentC,\n          createElement(SFC, { key: 'sfc3' }),\n        ),\n        container,\n      );\n\n      const FragmentAHtml = '<div id=\"a1\">A1</div><div>A2</div>';\n      const FragmentBHtml = '<div id=\"b1\">B1</div>';\n      const FragmentCHtml = '<div id=\"c1\">C1</div><div>C2</div><div>C3</div>';\n      const SFCHtml = '<span>1</span>' + FragmentCHtml + '<span>2</span>';\n\n      expect(container.innerHTML).toBe(\n        FragmentAHtml +\n          SFCHtml +\n          FragmentBHtml +\n          SFCHtml +\n          FragmentCHtml +\n          SFCHtml,\n      );\n\n      // Switch order\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement(SFC, { key: 'sfc3' }),\n          fragmentA,\n          createElement(SFC, { key: 'sfc1' }),\n          fragmentC,\n          createElement(SFC, { key: 'sfc2' }),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        SFCHtml + FragmentAHtml + SFCHtml + FragmentCHtml + SFCHtml,\n      );\n\n      // Switch order again\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement('div', { key: '1' }, '1'),\n          createElement(SFC, { key: 'sfc1' }),\n          createElement(SFC, { key: 'sfc2' }),\n          fragmentA,\n          fragmentC,\n          createElement('div', { key: '1' }, '2'),\n          createElement(SFC, { key: 'sfc3' }),\n        ),\n        container,\n      );\n\n      // Verify dom has changed and nodes are the same\n      expect(container.innerHTML).toBe(\n        '<div>1</div>' +\n          SFCHtml +\n          SFCHtml +\n          FragmentAHtml +\n          FragmentCHtml +\n          '<div>2</div>' +\n          SFCHtml,\n      );\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should be possible to render fragments JSX way', () => {\n      function Fragmenter({ first, mid, last, changeOrder }) {\n        if (changeOrder) {\n          return createElement(\n            Fragment,\n            null,\n            createElement('div', null, first),\n            createElement(\n              Fragment,\n              null,\n              'More',\n              null,\n              'Hey!',\n              createElement(\n                Fragment,\n                null,\n                createElement(Fragment, null, 'Large ', last),\n                createElement(Fragment, null, 'And Small'),\n              ),\n              createElement(Fragment, null, 'Nesting'),\n              mid,\n            ),\n            createElement('span', null, 'bar'),\n            null,\n          );\n        }\n        return createElement(\n          Fragment,\n          null,\n          createElement('div', null, first),\n          'Hey!',\n          createElement(\n            Fragment,\n            null,\n            'More',\n            createElement(Fragment, null, 'Nesting'),\n            mid,\n            createElement(\n              Fragment,\n              null,\n              createElement(Fragment, null, 'Large ', last),\n              createElement(Fragment, null, 'And Small'),\n            ),\n          ),\n          createElement('span', null, 'bar'),\n        );\n      }\n\n      let mountCounter = 0;\n      let unmountCounter = 0;\n\n      const FoobarCom = class FoobarCom extends Component<{\n        node: HTMLDivElement;\n      }> {\n        componentWillMount() {\n          mountCounter++;\n        }\n\n        componentWillUnmount() {\n          unmountCounter++;\n        }\n\n        render(props) {\n          return createElement(\n            Fragment,\n            null,\n            props.children,\n            createPortal(\n              createElement('div', null, 'InvisiblePortalCreator'),\n              props.node,\n            ),\n            null,\n            'Try out some crazy stuff',\n          );\n        }\n      };\n\n      const portalNode = document.createElement('div');\n\n      render(\n        createElement(\n          FoobarCom,\n          { node: portalNode },\n          createElement(Fragmenter, {\n            first: 'first',\n            mid: 'MID',\n            last: createElement('div', null, 'Why?'),\n            changeOrder: false,\n          }),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<div>first</div>Hey!MoreNestingMIDLarge <div>Why?</div>And Small<span>bar</span>Try out some crazy stuff',\n      );\n      expect(portalNode.innerHTML).toBe('<div>InvisiblePortalCreator</div>');\n\n      render(\n        createElement(\n          FoobarCom,\n          { node: portalNode },\n          createElement(Fragmenter, {\n            first: createElement('span', null, 'GoGo'),\n            mid: 'MID',\n            last: createElement('div', null, 'Why?'),\n            changeOrder: true,\n          }),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<div><span>GoGo</span></div>MoreHey!Large <div>Why?</div>And SmallNestingMID<span>bar</span>Try out some crazy stuff',\n      );\n      expect(portalNode.innerHTML).toBe('<div>InvisiblePortalCreator</div>');\n\n      render(\n        createElement(\n          FoobarCom,\n          { node: portalNode },\n          createElement(Fragmenter, {\n            first: 'first',\n            mid: 'MID',\n            last: createElement('div', null, 'Why?'),\n            changeOrder: false,\n          }),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<div>first</div>Hey!MoreNestingMIDLarge <div>Why?</div>And Small<span>bar</span>Try out some crazy stuff',\n      );\n      expect(portalNode.innerHTML).toBe('<div>InvisiblePortalCreator</div>');\n    });\n\n    it('Should render deeply nested fragment', () => {\n      function Fragmenter2() {\n        return createElement(\n          Fragment,\n          null,\n          createElement(\n            Fragment,\n            null,\n            createElement(\n              Fragment,\n              null,\n              createElement(\n                Fragment,\n                null,\n                createElement(\n                  Fragment,\n                  null,\n                  createElement(\n                    Fragment,\n                    null,\n                    createElement(\n                      Fragment,\n                      null,\n                      createElement(Fragment, null, 'Okay!'),\n                    ),\n                  ),\n                ),\n              ),\n            ),\n          ),\n        );\n      }\n\n      render(createElement(Fragmenter2, null), container);\n\n      expect(container.innerHTML).toBe('Okay!');\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should append DOM nodes to correct position when component root Fragmnet change', () => {\n      const TestRoot = class TestRoot extends Component {\n        render() {\n          return createElement(Fragment, null, this.props.children);\n        }\n      };\n\n      render(\n        createElement(\n          'div',\n          null,\n          createElement(\n            TestRoot,\n            null,\n            createElement('div', null, '1'),\n            createElement('div', null, '2'),\n          ),\n          createElement(\n            TestRoot,\n            null,\n            createElement('span', null, 'Ok'),\n            createElement('span', null, 'Test'),\n          ),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<div><div>1</div><div>2</div><span>Ok</span><span>Test</span></div>',\n      );\n\n      render(\n        createElement(\n          'div',\n          null,\n          createElement(\n            TestRoot,\n            null,\n            createElement('div', null, '1'),\n            createElement('div', null, '2'),\n            createElement('div', null, '3'),\n            createElement('div', null, '4'),\n          ),\n          createElement(TestRoot, null, createElement('div', null, 'Other')),\n        ),\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div><div>1</div><div>2</div><div>3</div><div>4</div><div>Other</div></div>',\n      );\n    });\n\n    it('Should not clear whole parent element when fragment children are cleared', () => {\n      const TestRoot = class TestRoot extends Component {\n        render() {\n          return createElement(Fragment, null, this.props.children);\n        }\n      };\n\n      render(\n        createElement(\n          'div',\n          null,\n          createElement(\n            TestRoot,\n            null,\n            createElement('div', null, '1'),\n            createElement('div', null, '2'),\n          ),\n          createElement(\n            TestRoot,\n            null,\n            createElement('span', null, 'Ok'),\n            createElement('span', null, 'Test'),\n          ),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<div><div>1</div><div>2</div><span>Ok</span><span>Test</span></div>',\n      );\n\n      render(\n        createElement(\n          'div',\n          null,\n          createElement(\n            TestRoot,\n            null,\n            createElement('div', null, '1'),\n            createElement('div', null, '2'),\n            createElement('div', null, '3'),\n            createElement('div', null, '4'),\n          ),\n          createElement(TestRoot, null),\n        ),\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div><div>1</div><div>2</div><div>3</div><div>4</div></div>',\n      );\n    });\n\n    it('Should move fragment and all its contents when using Fragment long syntax with keys', () => {\n      let unmountCounter = 0;\n      let mountCounter = 0;\n\n      const TestLifecycle = class TestLifecycle extends Component {\n        componentWillUnmount() {\n          unmountCounter++;\n        }\n\n        componentWillMount() {\n          mountCounter++;\n        }\n\n        render() {\n          return createElement(Fragment, null, this.props.children);\n        }\n      };\n\n      render(\n        createElement(\n          'div',\n          null,\n          createElement(\n            Fragment,\n            { key: '1' },\n            createElement(TestLifecycle, null, '1a'),\n            createElement(TestLifecycle, null, '1b'),\n          ),\n          createElement(\n            Fragment,\n            { key: '2' },\n            createElement(TestLifecycle, null, '2a'),\n            createElement(TestLifecycle, null, '2b'),\n          ),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div>1a1b2a2b</div>');\n      expect(unmountCounter).toBe(0);\n      expect(mountCounter).toBe(4);\n\n      render(\n        createElement(\n          'div',\n          null,\n          createElement(\n            Fragment,\n            { key: '2' },\n            createElement(TestLifecycle, null, '2a'),\n            createElement(TestLifecycle, null, '2b'),\n            createElement(TestLifecycle, null, '2c'),\n          ),\n          createElement(\n            Fragment,\n            { key: '1' },\n            createElement(TestLifecycle, null, '1a'),\n            createElement(TestLifecycle, null, '1b'),\n          ),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div>2a2b2c1a1b</div>');\n      expect(unmountCounter).toBe(0);\n      expect(mountCounter).toBe(5);\n\n      render(\n        createElement(\n          'div',\n          null,\n          createElement(\n            Fragment,\n            { key: '3' },\n            createElement(TestLifecycle, null, '3a'),\n            createElement(TestLifecycle, null, '3b'),\n            createElement(TestLifecycle, null, '3c'),\n          ),\n          createElement(\n            Fragment,\n            { key: '2' },\n            createElement(TestLifecycle, null, '2a'),\n            createElement(TestLifecycle, null, '2Patched'),\n          ),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div>3a3b3c2a2Patched</div>');\n      expect(unmountCounter).toBe(3);\n      expect(mountCounter).toBe(8);\n    });\n\n    it('Should unmount empty fragments', () => {\n      render(\n        createElement(Fragment, null, createElement(Fragment, null)),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('');\n\n      render(\n        createElement(Fragment, null, createElement('div', null)),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div></div>');\n\n      render(\n        createElement(Fragment, null, createElement(Fragment, null)),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('');\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should be possible to replace last element in fragment', () => {\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement(\n            Fragment,\n            null,\n            createElement('span', null, '1a'),\n            createElement('span', null, '1b'),\n            createElement('div', null, '1c'),\n          ),\n          createElement(\n            Fragment,\n            null,\n            createElement('span', null, '2a'),\n            createElement('span', null, '2b'),\n            createElement('span', null, '2c'),\n          ),\n          createElement(Fragment, null),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<span>1a</span><span>1b</span><div>1c</div><span>2a</span><span>2b</span><span>2c</span>',\n      );\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement(\n            Fragment,\n            null,\n            createElement('span', null, '1a'),\n            createElement('span', null, '1c'),\n          ),\n          createElement(\n            Fragment,\n            null,\n            createElement('span', null, '2a'),\n            createElement('span', null, '2b'),\n            createElement('span', null, '2c'),\n          ),\n          createElement(Fragment, null),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<span>1a</span><span>1c</span><span>2a</span><span>2b</span><span>2c</span>',\n      );\n\n      render(\n        createElement(Fragment, null, createElement(Fragment, null)),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('');\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should mount Fragment with invalid children', () => {\n      render(createElement(Fragment, null, null, undefined), container);\n\n      expect(container.innerHTML).toBe('');\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should mount Fragment with invalid children #2', () => {\n      function Foobar() {\n        return null;\n      }\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          null,\n          createElement(Foobar, null),\n          undefined,\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('');\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should mount Fragment with invalid children #2', () => {\n      let add = false;\n\n      function Foobar() {\n        if (add) {\n          return createElement('div', null, 'Ok');\n        }\n        return null;\n      }\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          null,\n          createElement(Foobar, null),\n          undefined,\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('');\n\n      add = true;\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          null,\n          createElement(Foobar, null),\n          undefined,\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div>Ok</div>');\n    });\n\n    it('Should be possible to update from 0 to 1', () => {\n      function Foobar() {\n        return createElement('div', null, 'Ok');\n      }\n\n      let content: (VNode | null)[] = [null];\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement('span', null, '1'),\n          createElement(Fragment, null, content),\n          createElement('span', null, '2'),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<span>1</span><span>2</span>');\n\n      content = [createElement(Foobar, null)];\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement('span', null, '1'),\n          createElement(Fragment, null, content),\n          createElement('span', null, '2'),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<span>1</span><div>Ok</div><span>2</span>',\n      );\n    });\n\n    it('Should be possible to update from 0 to 1 fragment -> fragment', () => {\n      function Foobar() {\n        return createElement('div', null, 'Ok');\n      }\n\n      let content: (VNode | null)[] = [];\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement('span', null, '1'),\n          createElement(Fragment, null, content),\n          createElement('span', null, '2'),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<span>1</span><span>2</span>');\n\n      content = [createElement(Fragment, null, createElement(Foobar, null))];\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement('span', null, '1'),\n          createElement(Fragment, null, content),\n          createElement('span', null, '2'),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe(\n        '<span>1</span><div>Ok</div><span>2</span>',\n      );\n    });\n\n    it('Should be possible to mount and patch single component fragment children', () => {\n      let counter = 0;\n\n      const Foobar = class Foobar extends Component {\n        componentWillMount() {\n          counter++;\n        }\n\n        render() {\n          return null;\n        }\n      };\n\n      render(createElement(Fragment, null), container);\n\n      render(\n        createElement(Fragment, null, createElement(Foobar, null)),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('');\n      expect(counter).toBe(1);\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement('div', null, 'Ok'),\n          createElement(Foobar, null),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div>Ok</div>');\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should be possible to mount and patch single component fragment children - variation 2', () => {\n      let counter = 0;\n\n      const Foobar = class Foobar extends Component {\n        componentWillMount() {\n          counter++;\n        }\n\n        render() {\n          return null;\n        }\n      };\n\n      let nodes: (VNode | null)[] = [];\n\n      render(createElement(Fragment, null, nodes), container);\n\n      nodes = [createElement(Foobar, null)];\n\n      render(createElement(Fragment, null, nodes), container);\n\n      nodes = [\n        createElement(Foobar, null),\n        createElement(Foobar, null),\n        createElement(Foobar, null),\n      ];\n\n      render(createElement(Fragment, null, nodes), container);\n\n      nodes = [];\n\n      render(createElement(Fragment, null, nodes), container);\n\n      expect(container.innerHTML).toBe('');\n      expect(counter).toBe(3);\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement('div', null, 'Ok'),\n          createElement(Foobar, null),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div>Ok</div>');\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should be possible to patch single fragment child component', () => {\n      let counter = 0;\n\n      const Foobar = class Foobar extends Component {\n        componentWillMount() {\n          counter++;\n        }\n\n        render() {\n          return null;\n        }\n      };\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement(Fragment, null, createElement(Foobar, null)),\n          createElement(Fragment, null, createElement(Foobar, null)),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('');\n      expect(counter).toBe(2);\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement(Fragment, null),\n          createElement(Fragment, null, createElement(Foobar, null)),\n          createElement(Fragment, null, createElement(Foobar, null)),\n          createElement(Fragment, null),\n          createElement(Foobar, null),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('');\n      expect(counter).toBe(4);\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement('div', null, 'Ok'),\n          createElement(Foobar, null),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div>Ok</div>');\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should be possible to mount and patch single component fragment children', () => {\n      const Foobar = class Foobar extends Component {\n        render() {\n          return null;\n        }\n      };\n\n      render(\n        createElement(Fragment, null, createElement(Foobar, null)),\n        container,\n      );\n\n      render(\n        createElement(Fragment, null, createElement(Foobar, null)),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('');\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement('div', null, 'Ok'),\n          createElement(Foobar, null),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div>Ok</div>');\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should be possible to mount and patch single component fragment children #2', () => {\n      const Foobar = class Foobar extends Component {\n        render() {\n          return null;\n        }\n      };\n\n      render(createElement(Fragment, null, null), container);\n\n      render(\n        createElement(Fragment, null, createElement(Foobar, null)),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('');\n\n      render(\n        createElement(\n          Fragment,\n          null,\n          createElement('div', null, 'Ok'),\n          createElement(Foobar, null),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div>Ok</div>');\n\n      render(null, container);\n\n      expect(container.innerHTML).toBe('');\n    });\n\n    it('Should mount fragment children to correct position Github #1412', () => {\n      const f = (...xs) => createFragment(xs, 0);\n\n      interface ArticlesState {\n        articles: string[];\n        sections: string[];\n      }\n\n      class Articles extends Component<unknown, ArticlesState> {\n        state: ArticlesState;\n\n        constructor() {\n          super();\n          this.state = {\n            articles: ['id2', 'id3'],\n            sections: ['id0', 'id1'],\n          };\n        }\n\n        componentDidMount() {\n          expect(container.innerHTML).toEqual(\n            '<h1>App</h1><section><h2>id0</h2><aside>Today</aside><article>id2</article><article>id3</article></section><section><h2>id1</h2><aside>Today</aside><article>id2</article><article>id3</article></section><footer>2018</footer>',\n          );\n\n          this.setState({ sections: [] });\n\n          rerender();\n\n          expect(container.innerHTML).toEqual(\n            '<h1>App</h1><footer>2018</footer>',\n          );\n\n          this.setState({ articles: ['id2', 'id3'], sections: ['id0', 'id1'] });\n\n          rerender();\n\n          expect(container.innerHTML).toEqual(\n            '<h1>App</h1><section><h2>id0</h2><aside>Today</aside><article>id2</article><article>id3</article></section><section><h2>id1</h2><aside>Today</aside><article>id2</article><article>id3</article></section><footer>2018</footer>',\n          );\n        }\n\n        render() {\n          return f(\n            this.state.sections.map((section) =>\n              createElement('section', null, [\n                createElement('h2', null, section),\n                this.state.articles.map((article) =>\n                  f(\n                    article === 'id2' && createElement('aside', null, 'Today'),\n                    createElement('article', null, article),\n                  ),\n                ),\n              ]),\n            ),\n          );\n        }\n      }\n\n      class App extends Component {\n        render() {\n          return f(\n            createElement('h1', null, 'App'),\n            createElement(Articles),\n            createElement('footer', null, '2018'),\n          );\n        }\n      }\n\n      render(createElement(App), container);\n\n      rerender();\n    });\n\n    it('Should re-mount fragment children to correct position when edge is component', () => {\n      const f = (...xs) => createFragment(xs, 0);\n\n      interface ArticlesState {\n        articles: string[];\n        sections: string[];\n      }\n\n      class Articles extends Component<unknown, ArticlesState> {\n        state: ArticlesState;\n        constructor() {\n          super();\n          this.state = { articles: ['id2', 'id3'], sections: ['id0', 'id1'] };\n        }\n\n        componentDidMount() {\n          expect(container.innerHTML).toEqual(\n            '<h1>App</h1><section><h2>id0</h2><aside>Today</aside><article>id2</article><article>id3</article></section><div>end</div><section><h2>id1</h2><aside>Today</aside><article>id2</article><article>id3</article></section><div>end</div><footer>2018</footer><div>1</div><div>2</div>',\n          );\n\n          this.setState({ sections: [] });\n\n          rerender();\n\n          expect(container.innerHTML).toEqual(\n            '<h1>App</h1><footer>2018</footer><div>1</div><div>2</div>',\n          );\n\n          this.setState({ articles: ['id2', 'id3'], sections: ['id0', 'id1'] });\n\n          rerender();\n\n          expect(container.innerHTML).toEqual(\n            '<h1>App</h1><section><h2>id0</h2><aside>Today</aside><article>id2</article><article>id3</article></section><div>end</div><section><h2>id1</h2><aside>Today</aside><article>id2</article><article>id3</article></section><div>end</div><footer>2018</footer><div>1</div><div>2</div>',\n          );\n        }\n\n        render() {\n          return f(\n            this.state.sections.map((section) =>\n              createElement(Section, {\n                children: [\n                  createElement('h2', null, section),\n                  this.state.articles.map((article) =>\n                    f(\n                      article === 'id2' &&\n                        createElement('aside', null, 'Today'),\n                      createElement('article', null, article),\n                    ),\n                  ),\n                ],\n              }),\n            ),\n          );\n        }\n      }\n\n      function Section(props) {\n        return f(\n          createElement('section', null, props.children),\n          createElement('div', null, 'end'),\n        );\n      }\n\n      function EdgeComponent() {\n        return f(\n          createElement('footer', null, '2018'),\n          createElement('div', null, '1'),\n          createElement('div', null, '2'),\n        );\n      }\n\n      class App extends Component {\n        render() {\n          return f(\n            createElement('h1', null, 'App'),\n            createElement(Articles),\n            createElement(EdgeComponent),\n          );\n        }\n      }\n\n      render(createElement(App), container);\n\n      rerender();\n    });\n\n    it('Should append more fragment children to correct position when edge is component', () => {\n      const f = (...xs) => createFragment(xs, 0);\n\n      interface ArticlesState {\n        articles: string[];\n        sections: string[];\n      }\n\n      class Articles extends Component<unknown, ArticlesState> {\n        state: ArticlesState;\n        constructor() {\n          super();\n          this.state = { articles: ['id2', 'id3'], sections: ['id0', 'id1'] };\n        }\n\n        componentDidMount() {\n          expect(container.innerHTML).toEqual(\n            '<h1>App</h1><section><h2>id0</h2><aside>Today</aside><article>id2</article><article>id3</article></section><div>end</div><section><h2>id1</h2><aside>Today</aside><article>id2</article><article>id3</article></section><div>end</div><footer>2018</footer><div>1</div><div>2</div>',\n          );\n\n          this.setState({ articles: [], sections: ['id0'] });\n\n          rerender();\n\n          expect(container.innerHTML).toEqual(\n            '<h1>App</h1><section><h2>id0</h2></section><div>end</div><footer>2018</footer><div>1</div><div>2</div>',\n          );\n\n          this.setState({ articles: ['id2', 'id3'], sections: ['id0', 'id1'] });\n\n          rerender();\n\n          expect(container.innerHTML).toEqual(\n            '<h1>App</h1><section><h2>id0</h2><aside>Today</aside><article>id2</article><article>id3</article></section><div>end</div><section><h2>id1</h2><aside>Today</aside><article>id2</article><article>id3</article></section><div>end</div><footer>2018</footer><div>1</div><div>2</div>',\n          );\n        }\n\n        render() {\n          return f(\n            this.state.sections.map((section) =>\n              createElement(Section, {\n                children: [\n                  createElement('h2', null, section),\n                  this.state.articles.map((article) =>\n                    f(\n                      article === 'id2' &&\n                        createElement('aside', null, 'Today'),\n                      createElement('article', null, article),\n                    ),\n                  ),\n                ],\n              }),\n            ),\n          );\n        }\n      }\n\n      function Section(props) {\n        return f(\n          createElement('section', null, props.children),\n          createElement('div', null, 'end'),\n        );\n      }\n\n      function EdgeComponent() {\n        return f(\n          createElement('footer', null, '2018'),\n          createElement('div', null, '1'),\n          createElement('div', null, '2'),\n        );\n      }\n\n      class App extends Component {\n        render() {\n          return f(\n            createElement('h1', null, 'App'),\n            createElement(Articles),\n            createElement(EdgeComponent),\n          );\n        }\n      }\n\n      render(createElement(App), container);\n\n      rerender();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/createElement.spec.ts",
    "content": "import {\n  Component,\n  createRef,\n  forwardRef,\n  Fragment,\n  type Inferno,\n  type RefObject,\n  render,\n} from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('CreateElement (non-JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should handle events correctly when having multiple children', () => {\n    let triggered = false;\n\n    const App = () => {\n      return createElement(\n        'div',\n        null,\n        createElement('div', { className: 'title' }, 'Example'),\n        createElement(\n          'button',\n          {\n            type: 'button',\n            onClick: () => {\n              triggered = !triggered;\n            },\n          },\n          'Do a thing',\n        ),\n      );\n    };\n\n    render(App(), container);\n    expect(container.innerHTML).toBe(\n      '<div><div class=\"title\">Example</div><button type=\"button\">Do a thing</button></div>',\n    );\n    expect(triggered).toBe(false);\n\n    const buttons = container.querySelectorAll('button');\n    for (const button of buttons) {\n      button.click();\n    }\n\n    expect(triggered).toBe(true);\n  });\n\n  it('Should handle events correctly when having single child', () => {\n    let triggered = false;\n\n    const app = () => {\n      return createElement(\n        'div',\n        null,\n        createElement(\n          'button',\n          {\n            type: 'button',\n            onClick: () => {\n              triggered = !triggered;\n            },\n          },\n          'Do a thing',\n        ),\n      );\n    };\n\n    render(app(), container);\n    expect(container.innerHTML).toBe(\n      '<div><button type=\"button\">Do a thing</button></div>',\n    );\n    expect(triggered).toBe(false);\n\n    const buttons = container.querySelectorAll('button');\n    for (const button of buttons) {\n      button.click();\n    }\n\n    expect(triggered).toBe(true);\n  });\n\n  it('Should allow passing childs through \"children\" property (native component)', () => {\n    const app = () => {\n      return createElement(\n        'div',\n        null,\n        createElement('button', {\n          type: 'button',\n          children: ['Do a thing'],\n        }),\n      );\n    };\n\n    render(app(), container);\n    expect(container.innerHTML).toBe(\n      '<div><button type=\"button\">Do a thing</button></div>',\n    );\n  });\n\n  it('Should allow passing childs through \"children\" property (custom component)', () => {\n    const Button = (props) => createElement('button', props);\n    const app = () => {\n      return createElement(\n        'div',\n        null,\n        createElement(Button, {\n          type: 'button',\n          children: ['Do a thing'],\n        }),\n      );\n    };\n\n    render(app(), container);\n    expect(container.innerHTML).toBe(\n      '<div><button type=\"button\">Do a thing</button></div>',\n    );\n  });\n\n  it('Should handle node with hooks and key', (done) => {\n    const node = () => createElement('div', { key: 'key2' }, 'Hooks');\n    const app = createElement(node, {\n      key: 'key1',\n      onComponentDidMount(domNode) {\n        expect(app.key).toBe('key1');\n        expect(domNode.tagName).toBe('DIV');\n        done();\n      },\n    });\n\n    render(app, container);\n    expect(container.innerHTML).toBe('<div>Hooks</div>');\n  });\n\n  it('Should handle node with children but no props', () => {\n    const node = () => createElement('div', null, 'Hooks');\n    const app = createElement(node, null, 'Hooks');\n\n    render(app, container);\n    expect(container.innerHTML).toBe('<div>Hooks</div>');\n  });\n\n  it('Should handle node with refs', (done) => {\n    let myRef: any = 'myRef';\n\n    const app = () => {\n      const node: Inferno.StatelessComponent<any> = () =>\n        createElement('a', {\n          ref: (c) => (myRef = c),\n        });\n\n      return createElement(node, {\n        onComponentDidMount() {\n          expect(myRef.tagName).toBe('A');\n          done();\n        },\n      });\n    };\n    render(createElement(app, null), container);\n  });\n\n  describe('Fragments', () => {\n    it('Should render Fragment with key', () => {\n      render(\n        createElement(\n          Fragment,\n          { key: 'first' },\n          createElement('div', null, 'Ok'),\n          createElement('span', null, 'Test'),\n        ),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div>Ok</div><span>Test</span>');\n\n      const div = container.querySelector('div');\n      const span = container.querySelector('span');\n\n      render(\n        createElement(\n          Fragment,\n          { key: 'foobar' },\n          createElement('div', null, 'Ok'),\n          createElement('span', null, 'Test'),\n        ),\n        container,\n      );\n\n      // Verify key works\n      expect(container.innerHTML).toBe('<div>Ok</div><span>Test</span>');\n\n      expect(div).not.toBe(container.querySelector('div'));\n      expect(span).not.toBe(container.querySelector('span'));\n    });\n  });\n\n  it('Should be possible to forward createRef', () => {\n    // TODO: Investigate how these refs should be typed\n    const FancyButton = forwardRef<HTMLButtonElement, { children?: any }>(\n      (props, ref: any) =>\n        createElement(\n          'button',\n          { ref, className: 'FancyButton' },\n          props.children,\n        ),\n    );\n\n    expect(FancyButton.render).toBeDefined();\n\n    class Hello extends Component {\n      btn: RefObject<HTMLButtonElement>;\n\n      constructor(props) {\n        super(props);\n\n        // You can now get a ref directly to the DOM button:\n        this.btn = createRef();\n      }\n\n      componentDidMount() {\n        expect(this.btn.current).toBe(container.querySelector('button'));\n      }\n\n      render() {\n        return createElement(\n          FancyButton,\n          { ref: this.btn as any },\n          'Click me!',\n        );\n      }\n    }\n\n    render(createElement(Hello), container);\n\n    expect(container.innerHTML).toBe(\n      '<button class=\"FancyButton\">Click me!</button>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/createElementTyped.spec.tsx",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('CreateElement (non-JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should render zero children', () => {\n    const App = () => createElement('div', null);\n    render(App(), container);\n  });\n\n  it('Should render null children', () => {\n    const App = () => createElement('div', null, null);\n    render(App(), container);\n  });\n\n  it('Should render undefined children', () => {\n    const App = () => createElement('div', null, undefined);\n    render(App(), container);\n  });\n\n  it('Should render one child', () => {\n    const App = () =>\n      createElement(\n        'div',\n        null,\n        createElement('div', { className: 'title' }, 'Example'),\n      );\n\n    render(App(), container);\n  });\n\n  it('Should render multiple children', () => {\n    const App = () =>\n      createElement(\n        'div',\n        null,\n        createElement('div', { className: 'title' }, 'Example'),\n        createElement('button', { type: 'button' }, 'Do a thing'),\n      );\n\n    render(App(), container);\n  });\n\n  it('Should render array of children', () => {\n    const App = () =>\n      createElement('div', null, [\n        createElement('div', { className: 'title' }, 'Example'),\n        createElement('button', { type: 'button' }, 'Do a thing'),\n      ]);\n\n    render(App(), container);\n  });\n\n  it('Should check component props', () => {\n    interface MyComponentProps {\n      className: string;\n    }\n\n    class App extends Component<MyComponentProps, any> {\n      public render() {\n        return createElement(\n          'div',\n          { className: this.props.className },\n          createElement('div', { className: 'title' }, 'Example'),\n          createElement('hr'),\n        );\n      }\n    }\n\n    render(createElement(App, { className: 'App' }), container);\n\n    /** Should be an error if uncommented: */\n    // render(createElement(App, { className: 1 }), container);\n    // render(createElement(App, {}), container);\n\n    /** Would like to be an error, but it'd break createElement('hr'): */\n    render(createElement(App), container);\n  });\n\n  it('Should check functional component props', () => {\n    const App = ({ className }: { className: string }) =>\n      createElement(\n        'div',\n        { className },\n        createElement('div', { className: 'title' }, 'Example'),\n        createElement('hr'),\n      );\n\n    render(createElement(App, { className: 'App' }), container);\n\n    /** Should be an error if uncommented: */\n    // render(createElement(App, { className: 1 }), container);\n    // render(createElement(App, {}), container);\n\n    /** Would like to be an error but it'd break createElement('hr'): */\n    render(createElement(App), container);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/creation.spec.ts",
    "content": "import { render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('Creation - (non-JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  const tests = [\n    {\n      description: 'should render div with span child',\n      template: () => {\n        return createElement('div', null, createElement('span'));\n      },\n      tagName: 'div',\n      children: 1,\n      textContent: '',\n    },\n    {\n      description: 'should render span with span child',\n      template: () => createElement('span', null, createElement('span')),\n      tagName: 'span',\n      children: 1,\n      textContent: '',\n    },\n    {\n      description: 'should render div with two span children',\n      template: () =>\n        createElement('div', null, createElement('div'), createElement('div')),\n      tagName: 'div',\n      children: 2,\n      textContent: '',\n    },\n    {\n      description:\n        'should render div with three span children and unset middle child',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span'),\n          null,\n          createElement('span'),\n        ),\n      tagName: 'div',\n      children: 2,\n      textContent: '',\n    },\n    {\n      description:\n        'should render div with three span children and unset first, and middle child',\n      template: () =>\n        createElement('div', null, null, null, createElement('span')),\n      tagName: 'div',\n      children: 1,\n      textContent: '',\n    },\n    {\n      description:\n        'should render div with three span children and unset first, and middle child',\n      template: () => createElement('div', null, null, null, null),\n      tagName: 'div',\n      children: 0,\n      textContent: '',\n    },\n    {\n      description: 'should render div with two null children and one text node',\n      template: () => createElement('div', null, null, 'Baboy', null),\n      tagName: 'div',\n      children: 1,\n      textContent: 'Baboy',\n    },\n    {\n      description: 'should render div with one textNode and a span children',\n      template: () =>\n        createElement('div', null, 'Hello!', null, createElement('span')),\n      tagName: 'div',\n      children: 2,\n      textContent: 'Hello!',\n    },\n    {\n      description: 'should render div with two textNodes and a span children',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          'Hello, ',\n          null,\n          'World!',\n          createElement('span'),\n        ),\n      tagName: 'div',\n      children: 3,\n      textContent: 'Hello, World!',\n    },\n    {\n      description:\n        'should render div with two textNodes and a two span children',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          'Hello, ',\n          createElement('span'),\n          'World!',\n          createElement('span'),\n        ),\n      tagName: 'div',\n      children: 4,\n      textContent: 'Hello, World!',\n    },\n    {\n      description:\n        'should render div with two textNodes and one span children, and span with textNode',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          'Hello',\n          createElement('span'),\n          ', ',\n          createElement('span', null, 'World!'),\n        ),\n      tagName: 'div',\n      children: 4,\n      textContent: 'Hello, World!',\n    },\n    {\n      description:\n        'should render div with tree null values in an array for children',\n      template: () => createElement('div', null, null, null, null),\n      tagName: 'div',\n      children: 0,\n      textContent: '',\n    },\n    {\n      description:\n        'should render div with b child, and tree null values in an array for children',\n      template: () =>\n        createElement('div', null, createElement('b', null, null, null, null)),\n      tagName: 'div',\n      children: 1,\n      textContent: '',\n    },\n    {\n      description:\n        'should render div with b child, and number and two null values in an array for children',\n      template: () =>\n        createElement('div', null, createElement('b', null, null, 123, null)),\n      tagName: 'div',\n      children: 1,\n      textContent: '123',\n    },\n    {\n      description: 'should render empty div',\n      template: () => createElement('div'),\n      tagName: 'div',\n      children: 0,\n      textContent: '',\n    },\n    {\n      description: 'should render empty span',\n      template: () => createElement('span'),\n      tagName: 'span',\n      children: 0,\n      textContent: '',\n    },\n  ];\n\n  for (const test of tests) {\n    it(test.description, () => {\n      render(test.template(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.tagName.toLowerCase()).toBe(test.tagName);\n      expect(container.firstChild.childNodes.length).toBe(test.children);\n      expect(container.firstChild.textContent).toBe(test.textContent);\n\n      render(test.template(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.firstChild.tagName.toLowerCase()).toBe(test.tagName);\n      expect(container.firstChild.childNodes.length).toBe(test.children);\n    });\n  }\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/elements.spec.jsx",
    "content": "import { render, createVNode } from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\ndescribe('Elements (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should render a simple div', () => {\n    render(<div />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    render(<div />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n  });\n\n  it('should render a simple div with multiple children', () => {\n    render(\n      <div>\n        <span />\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n    render(\n      <div>\n        <span />\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n    render(<div />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(0);\n    render(\n      <div>\n        <span />\n        <span />\n        <span />\n        <span />\n        <span />\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(5);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n\n    render(\n      <div>\n        <span />\n        <span />\n        <span />\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n    render(undefined, container);\n    render(\n      <div>\n        <span />\n        <b>Hello, World!</b>\n        <span />\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n  });\n\n  it('should render a simple div with multiple children #2', () => {\n    const items = [1, 2, 3];\n    const header = 'Hello ';\n\n    render(\n      <div>\n        {header}\n        {items}\n      </div>,\n      container,\n    );\n    expect(container.firstChild.innerHTML).toBe('Hello 123');\n\n    render(\n      <div>\n        {header}\n        {[4, 5, 6]}\n      </div>,\n      container,\n    );\n    expect(container.firstChild.innerHTML).toBe('Hello 456');\n  });\n\n  it('should render a simple div with span child and dynamic id attribute', () => {\n    render(<div id={'hello'} />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(0);\n    expect(container.firstChild.getAttribute('id')).toBe('hello');\n\n    render(<div id={null} />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(0);\n    expect(container.firstChild.getAttribute('id')).toBe(null);\n\n    render(<div className={'hello'} />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(0);\n    expect(container.firstChild.getAttribute('class')).toBe('hello'); // class attribute exist!\n\n    render(<div id=\"hello\" />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(0);\n    expect(container.firstChild.getAttribute('id')).toBe('hello');\n\n    // unset\n    render(null, container);\n    expect(container.nodeName).toBe('DIV');\n    expect(container.childNodes.length).toBe(0);\n  });\n\n  it('should render a simple div with span child and various dynamic attributes', () => {\n    render(<div id={'hello'} />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(0);\n    expect(container.firstChild.getAttribute('id')).toBe('hello');\n\n    render(<div />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(0);\n\n    render(<div className={'hello'} />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(0);\n    expect(container.firstChild.getAttribute('class')).toBe('hello');\n\n    render(null, container);\n    expect(container.nodeName).toBe('DIV');\n    expect(container.childNodes.length).toBe(0);\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should render a simple div with dynamic span child', () => {\n    const child = <span />;\n\n    render(<div>{undefined}</div>, container);\n    render(<div>{child}</div>, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n    render(<div>{null}</div>, container);\n    render(<div>{child}</div>, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n    // unset\n    render(null, container);\n    expect(container.nodeName).toBe('DIV');\n    expect(container.childNodes.length).toBe(0);\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should render a advanced div with static child and dynamic attributes', () => {\n    let attrs;\n\n    attrs = 'id#1';\n\n    render(\n      <div>\n        <div id={attrs} />\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.getAttribute('id')).toBe('id#1');\n\n    attrs = null;\n\n    render(\n      <div>\n        <div id={attrs} />\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.getAttribute('id')).toBe(null);\n\n    attrs = undefined;\n\n    render(<div id={attrs} />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(0);\n    expect(container.firstChild.getAttribute('id')).toBe(null);\n\n    attrs = 'id#4';\n\n    render(\n      <div>\n        <div id={attrs} />\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.getAttribute('id')).toBe('id#4');\n\n    attrs = 13 - (44 * 4) / 4;\n\n    let b = <b className={123}>Hello, World!</b>;\n    let n = <n>{b}</n>;\n\n    render(\n      <div className=\"Hello, World!\">\n        <span>\n          <div id={attrs}>{n}</div>\n        </span>\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe('Hello, World!');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n    expect(container.firstChild.firstChild.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.firstChild.getAttribute('id')).toBe(\n      '-31',\n    );\n    expect(container.firstChild.firstChild.firstChild.firstChild.nodeName).toBe(\n      'N',\n    );\n    expect(\n      container.firstChild.firstChild.firstChild.firstChild.firstChild.nodeName,\n    ).toBe('B');\n    expect(\n      container.firstChild.firstChild.firstChild.firstChild.firstChild\n        .innerHTML,\n    ).toBe('Hello, World!');\n    expect(\n      container.firstChild.firstChild.firstChild.firstChild.firstChild.getAttribute(\n        'class',\n      ),\n    ).toBe('123');\n\n    attrs = 13 - (44 * 4) / 4;\n\n    b = <b className={1243}>Hello, World!</b>;\n    n = <n>{b}</n>;\n\n    render(\n      <div className=\"Hello, World!\">\n        <span>\n          <div id={attrs}>{n}</div>\n        </span>\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe('Hello, World!');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n    expect(container.firstChild.firstChild.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.firstChild.getAttribute('id')).toBe(\n      '-31',\n    );\n    expect(container.firstChild.firstChild.firstChild.firstChild.nodeName).toBe(\n      'N',\n    );\n    expect(\n      container.firstChild.firstChild.firstChild.firstChild.firstChild.nodeName,\n    ).toBe('B');\n    expect(\n      container.firstChild.firstChild.firstChild.firstChild.firstChild\n        .innerHTML,\n    ).toBe('Hello, World!');\n    expect(\n      container.firstChild.firstChild.firstChild.firstChild.firstChild.getAttribute(\n        'class',\n      ),\n    ).toBe('1243');\n\n    // unset\n    render(null, container);\n    expect(container.nodeName).toBe('DIV');\n    expect(container.childNodes.length).toBe(0);\n\n    attrs = 'id#444';\n\n    render(\n      <div className=\"Hello, Dominic\" id={attrs}>\n        <div id={attrs} />\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe('Hello, Dominic');\n    expect(container.firstChild.getAttribute('id')).toBe('id#444');\n    expect(container.firstChild.firstChild.getAttribute('id')).toBe('id#444');\n\n    attrs = 'id#' + 333 - 333 / 3;\n\n    render(\n      <div className=\"Hello, Dominic\" id={attrs}>\n        <div id={attrs} />\n      </div>,\n      container,\n    );\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe('Hello, Dominic');\n    expect(container.firstChild.getAttribute('id')).toBe('NaN');\n    expect(container.firstChild.firstChild.getAttribute('id')).toBe('NaN');\n\n    // unset\n    render(null, container);\n    expect(container.nodeName).toBe('DIV');\n    expect(container.childNodes.length).toBe(0);\n  });\n\n  it('should render a simple div with dynamic span child and update to div child', () => {\n    let child = <span />;\n\n    render(<div>{child}</div>, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n\n    render(<div />, container);\n\n    child = <div />;\n\n    render(<div>{child}</div>, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('DIV');\n\n    child = (\n      <div>\n        <div />\n        <div />\n        <div />\n        <div />\n        <div />\n        <div />\n        <div />\n        <div />\n        <div />\n      </div>\n    );\n\n    render(<div>{child}</div>, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.childNodes.length).toBe(9);\n    expect(container.firstChild.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.firstChild.nodeName).toBe('DIV');\n    child = <div>Hello, World!</div>;\n\n    render(<div>{child}</div>, container);\n    expect(container.firstChild.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.innerHTML).toBe('Hello, World!');\n\n    render(<div>{null}</div>, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n\n    render(<div />, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n  });\n\n  it('should render and unset a simple div with dynamic span child', () => {\n    let child;\n\n    child = (\n      <span>\n        <span />\n        <span />\n      </span>\n    );\n\n    render(<div>{child}</div>, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.childNodes.length).toBe(2);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n    expect(container.firstChild.firstChild.firstChild.nodeName).toBe('SPAN');\n\n    render(<div>{null}</div>, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n\n    const divs = <div />;\n\n    child = (\n      <span>\n        <span>{divs}</span>\n      </span>\n    );\n\n    render(<div>{child}</div>, container);\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.nodeName).toBe('SPAN');\n    expect(container.firstChild.firstChild.firstChild.nodeName).toBe('SPAN');\n    expect(container.firstChild.firstChild.firstChild.firstChild.nodeName).toBe(\n      'DIV',\n    );\n  });\n\n  it('should render a simple div children set to undefined', () => {\n    render(<div>{undefined}</div>, container);\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.textContent).toBe('');\n\n    render(<div>{undefined}</div>, container);\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.textContent).toBe('');\n  });\n\n  it('should render a simple div children set to null', () => {\n    render(<div>{null}</div>, container);\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.textContent).toBe('');\n\n    render(<div>{null}</div>, container);\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.textContent).toBe('');\n\n    // unset\n    render(null, container);\n    expect(container.nodeName).toBe('DIV');\n    expect(container.childNodes.length).toBe(0);\n  });\n\n  it('should render a simple div children set to null', () => {\n    render(\n      <div>\n        <div>{null}</div>\n      </div>,\n      container,\n    );\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.textContent).toBe('');\n\n    render(\n      <div>\n        <div>{null}</div>\n      </div>,\n      container,\n    );\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.firstChild.textContent).toBe('');\n  });\n\n  it('should render a double div and a text node', () => {\n    render(<div>{<div>Hello, World!</div>}</div>, container);\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.textContent).toBe('Hello, World!');\n\n    render(<div>{null}</div>, container);\n\n    render(<div>{<div>Hello, Inferno!</div>}</div>, container);\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.textContent).toBe('Hello, Inferno!');\n  });\n\n  it('should render a single div with text node', () => {\n    render(\n      <div>\n        <span />\n        <span />\n      </div>,\n      container,\n    );\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.textContent).toBe('');\n\n    // unset\n    render(null, container);\n    expect(container.nodeName).toBe('DIV');\n    expect(container.childNodes.length).toBe(0);\n  });\n\n  it('should render a simple div with a text node', () => {\n    render(<div>Hello, world!</div>, container);\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.textContent).toBe('Hello, world!');\n\n    render(<div>Hello, world! 2</div>, container);\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.textContent).toBe('Hello, world! 2');\n  });\n\n  it('should render a simple div with attributes', () => {\n    render(<div id={123}>Hello, world!</div>, container);\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.getAttribute('id')).toBe('123');\n    expect(container.firstChild.textContent).toBe('Hello, world!');\n\n    render(<div id={'foo'}>Hello, world! 2</div>, container);\n\n    expect(container.nodeName).toBe('DIV');\n    expect(container.firstChild.getAttribute('id')).toBe('foo');\n    expect(container.firstChild.textContent).toBe('Hello, world! 2');\n  });\n\n  it('should render a simple div with inline style', () => {\n    render(\n      <div style=\"background-color:lightgrey;\">Hello, world!</div>,\n      container,\n    );\n\n    expect(container.nodeName).toBe('DIV');\n\n    render(<div id={'foo'}>Hello, world! 2</div>, container);\n\n    expect(container.nodeName).toBe('DIV');\n\n    // unset\n    render(null, container);\n    expect(container.nodeName).toBe('DIV');\n    expect(container.childNodes.length).toBe(0);\n  });\n\n  it('should render \"className\" attribute', () => {\n    render(<div className=\"123\" />, container);\n    expect(container.firstChild.getAttribute('class')).toEqual('123');\n\n    render(<div className={null} />, container);\n    expect(container.firstChild.className).toEqual('');\n\n    render(<div className={undefined} />, container);\n    expect(container.firstChild.className).toEqual('');\n\n    render(<div className=\"Inferno rocks!\" />, container);\n    expect(container.firstChild.className).toEqual('Inferno rocks!');\n    expect(container.firstChild.innerHTML).toBe('');\n  });\n\n  it(\"shouldn't render null value\", () => {\n    render(<input values={null} />, container);\n\n    expect(container.value).toBe(undefined);\n    expect(container.innerHTML).toBe('<input>');\n\n    render(<input values={undefined} />, container);\n    expect(container.value).toBe(undefined);\n\n    render(<input values={null} />, container);\n    expect(container.value).toBe(undefined);\n\n    expect(container.innerHTML).toBe('<input>');\n\n    render(null, container);\n    expect(container.nodeName).toBe('DIV');\n    expect(container.childNodes.length).toBe(0);\n  });\n\n  it('should set values as properties by default', () => {\n    render(<input title=\"Tip!\" />, container);\n\n    expect(container.firstChild.getAttribute('title')).toEqual('Tip!');\n    expect(container.innerHTML).toBe('<input title=\"Tip!\">');\n\n    render(<input name=\"Tip!\" />, container);\n\n    expect(container.firstChild.getAttribute('name')).toEqual('Tip!');\n    expect(container.innerHTML).toBe('<input name=\"Tip!\">');\n\n    render(<input title=\"Tip!\" />, container);\n\n    expect(container.firstChild.getAttribute('title')).toEqual('Tip!');\n    expect(container.innerHTML).toBe('<input title=\"Tip!\">');\n  });\n\n  it('should render a simple div with dynamic values and props', () => {\n    let val1, val2;\n\n    val1 = 'Inferno';\n    val2 = 'Sucks!';\n\n    render(\n      <div className=\"foo\">\n        <span className=\"bar\">{val1}</span>\n        <span className=\"yar\">{val2}</span>\n      </div>,\n      container,\n    );\n\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.childNodes.length).toBe(1);\n    expect(container.childNodes[0].childNodes[0].getAttribute('class')).toEqual(\n      'bar',\n    );\n    expect(container.childNodes[0].childNodes[0].textContent).toEqual(\n      'Inferno',\n    );\n    expect(container.childNodes[0].childNodes[1].getAttribute('class')).toEqual(\n      'yar',\n    );\n    expect(container.childNodes[0].childNodes[1].textContent).toEqual('Sucks!');\n\n    render(\n      <div className=\"fooo\">\n        <span className=\"bar\">{val1}</span>\n        <span className=\"yar\">{val2}</span>\n      </div>,\n      container,\n    );\n\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.childNodes.length).toBe(1);\n    expect(container.childNodes[0].childNodes[0].getAttribute('class')).toEqual(\n      'bar',\n    );\n    expect(container.childNodes[0].childNodes[0].textContent).toEqual(\n      'Inferno',\n    );\n    expect(container.childNodes[0].childNodes[1].getAttribute('class')).toEqual(\n      'yar',\n    );\n    expect(container.childNodes[0].childNodes[1].textContent).toEqual('Sucks!');\n  });\n\n  it('should properly render a input with download attribute', () => {\n    let val1;\n\n    val1 = 'false';\n\n    render(<input download={val1} />, container);\n\n    expect(container.firstChild.nodeName).toBe('INPUT');\n    expect(container.childNodes.length).toBe(1);\n    expect(container.firstChild.getAttribute('download')).toBe('false');\n\n    val1 = 'true';\n\n    render(<input download={val1} />, container);\n\n    expect(container.firstChild.nodeName).toBe('INPUT');\n    expect(container.childNodes.length).toBe(1);\n    expect(container.firstChild.getAttribute('download')).toBe('true');\n  });\n\n  it('should properly render \"className\" property on a custom element', () => {\n    render(<custom-elem className=\"Hello, world!\" />, container);\n\n    expect(container.firstChild.nodeName).toBe('CUSTOM-ELEM');\n    expect(container.childNodes.length).toBe(1);\n    expect(container.firstChild.getAttribute('class')).toBe('Hello, world!');\n\n    render(<custom-elem className=\"Hello, world!\" />, container);\n\n    expect(container.firstChild.nodeName).toBe('CUSTOM-ELEM');\n    expect(container.childNodes.length).toBe(1);\n    expect(container.firstChild.getAttribute('class')).toBe('Hello, world!');\n  });\n\n  it('should properly render \"width\" and \"height\" attributes', () => {\n    render(<img src=\"\" alt=\"Smiley face\" height={42} width={42} />, container);\n\n    expect(container.firstChild.nodeName).toBe('IMG');\n    expect(container.childNodes.length).toBe(1);\n    expect(container.firstChild.getAttribute('src')).toBe('');\n    expect(container.firstChild.getAttribute('alt')).toBe('Smiley face');\n    expect(container.firstChild.getAttribute('height')).toBe('42');\n    expect(container.firstChild.getAttribute('width')).toBe('42');\n\n    render(\n      <img src=\"\" alt=\"Smiley face\" height={42} width={42} fooBar={[]} />,\n      container,\n    );\n\n    expect(container.firstChild.nodeName).toBe('IMG');\n    expect(container.childNodes.length).toBe(1);\n    expect(container.firstChild.getAttribute('src')).toBe('');\n    expect(container.firstChild.getAttribute('alt')).toBe('Smiley face');\n    expect(container.firstChild.getAttribute('height')).toBe('42');\n    expect(container.firstChild.getAttribute('width')).toBe('42');\n  });\n\n  it('should properly render \"width\" and \"height\" attributes #2', () => {\n    render(\n      <input\n        type=\"file\"\n        multiple=\"multiple\"\n        capture=\"capture\"\n        accept=\"image/*\"\n      />,\n      container,\n    );\n\n    expect(container.firstChild.nodeName).toBe('INPUT');\n    expect(container.childNodes.length).toBe(1);\n    expect(container.firstChild.getAttribute('type')).toBe('file');\n\n    let multipleValue = container.firstChild.multiple;\n\n    // Inferno sets multiple using dom property always to boolean,\n    // but some browsers fe. IE9 still set it as multiple=\"multiple\" which also works as expected\n    if (typeof multipleValue === 'string') {\n      expect(multipleValue).toBe('multiple');\n    } else {\n      expect(multipleValue).toBe(true);\n    }\n\n    expect(container.firstChild.capture).toBeTruthy(); // true and \"true\" are both valid\n    // expect(container.firstChild.getAttribute('accept')).toBe('image/*');\n\n    render(\n      <input\n        type=\"file\"\n        multiple=\"multiple\"\n        capture=\"capture\"\n        accept=\"image/*\"\n      />,\n      container,\n    );\n\n    expect(container.firstChild.nodeName).toBe('INPUT');\n    expect(container.childNodes.length).toBe(1);\n    expect(container.firstChild.getAttribute('type')).toBe('file');\n\n    multipleValue = container.firstChild.multiple;\n\n    // Inferno sets multiple using dom property always to boolean,\n    // but some browsers fe. IE9 still set it as multiple=\"multiple\" which also works as expected\n    if (typeof multipleValue === 'string') {\n      expect(multipleValue).toBe('multiple');\n    } else {\n      expect(multipleValue).toBe(true);\n    }\n\n    expect(container.firstChild.capture).toBeTruthy(); // true and \"true\" are both valid;\n    // expect(container.firstChild.getAttribute('accept')).toBe('image/*');\n  });\n\n  it('should handle className', () => {\n    render(<div className={'foo'} />, container);\n    expect(container.firstChild.className).toBe('foo');\n    render(<div className={'bar'} />, container);\n    expect(container.firstChild.className).toBe('bar');\n    render(<div className={null} />, container);\n    expect(container.firstChild.className).toBe('');\n    render(<div className={undefined} />, container);\n    expect(container.firstChild.className).toBe('');\n    render(<svg className={'fooBar'} />, container);\n    expect(container.firstChild.getAttribute('class')).toBe('fooBar');\n  });\n\n  it('should remove attributes', () => {\n    render(<img height=\"17\" />, container);\n    expect(container.firstChild.hasAttribute('height')).toBe(true);\n    render(<img />, container);\n    expect(container.firstChild.hasAttribute('height')).toBe(false);\n    render(<img height={null} />, container);\n    expect(container.firstChild.hasAttribute('height')).toBe(false);\n  });\n\n  it('should remove properties #2', () => {\n    render(<div className=\"monkey\" />, container);\n    expect(container.firstChild.getAttribute('class')).toBe('monkey');\n    render(<div />, container);\n    expect(container.firstChild.className).toBe('');\n    render(<svg className=\"monkey\" />, container);\n    expect(container.firstChild.getAttribute('class')).toBe('monkey');\n    render(<svg />, container);\n    expect(container.firstChild.getAttribute('class')).toBe(null);\n  });\n\n  it('should not update when switching between null/undefined', () => {\n    render(<div id={null} />, container);\n    render(<div id={123} />, container);\n    render(<div id={null} />, container);\n    render(<div id={undefined} />, container);\n    render(<div />, container);\n    render(<div id=\"ltr\" />, container);\n    render(<div id={[]} />, container);\n  });\n\n  it('should render an iframe', () => {\n    render(<iframe src=\"http://infernojs.org\" />, container);\n    expect(container.firstChild.contentWindow).not.toBe(undefined);\n  });\n\n  it('should dangerously set innerHTML', () => {\n    render(\n      <div dangerouslySetInnerHTML={{ __html: 'Hello world!' }} />,\n      container,\n    );\n    expect(container.innerHTML).toBe('<div>Hello world!</div>');\n  });\n\n  it('Should not dangerously set innerHTML when previous is same as new one', () => {\n    render(<div dangerouslySetInnerHTML={{ __html: 'same' }} />, container);\n    expect(container.innerHTML).toBe('<div>same</div>');\n\n    render(<div dangerouslySetInnerHTML={{ __html: 'same' }} />, container);\n    expect(container.innerHTML).toBe('<div>same</div>');\n\n    render(<div dangerouslySetInnerHTML={{ __html: 'change' }} />, container);\n    expect(container.innerHTML).toBe('<div>change</div>');\n  });\n\n  it('Should throw error if __html property is not set', () => {\n    try {\n      render(<div dangerouslySetInnerHTML={{ __html: null }} />, container);\n    } catch (e) {\n      expect(e.message).toEqual(\n        'Inferno Error: dangerouslySetInnerHTML requires an object with a __html propety containing the innerHTML content.',\n      );\n    }\n  });\n\n  it('handles JSX spread props (including children)', () => {\n    const foo = {\n      children: 'Hello world!',\n      className: 'lol',\n    };\n    const bar = {\n      id: 'test',\n    };\n\n    render(<div {...foo} {...bar} />, container);\n    expect(container.innerHTML).toBe(\n      '<div class=\"lol\" id=\"test\">Hello world!</div>',\n    );\n  });\n\n  it('mixing JSX with non-JSX', () => {\n    render(<div>{createElement('div', null)}</div>, container);\n    expect(container.innerHTML).toBe('<div><div></div></div>');\n    render(<div>{createElement('span', null)}</div>, container);\n    expect(container.innerHTML).toBe('<div><span></span></div>');\n    render(<span>{createElement('div', null)}</span>, container);\n    expect(container.innerHTML).toBe('<span><div></div></span>');\n  });\n\n  it('should be able to construct input with Hooks, Events, Attributes defined', (done) => {\n    function test() {}\n\n    const obj = {\n      ref() {},\n      click() {},\n    };\n    const bool = false;\n    const newValue = 't';\n    const spread = { id: 'test' };\n\n    spyOn(obj, 'ref');\n    spyOn(obj, 'click');\n\n    render(\n      <input\n        type=\"text\"\n        ref={obj.ref}\n        spellcheck=\"false\"\n        readOnly={bool ? 'readonly' : false}\n        disabled={bool}\n        ondragenter={test}\n        ondragover={test}\n        value={newValue}\n        oninput={test}\n        onclick={obj.click}\n        className=\"edit-field\"\n        onkeydown={test}\n        onkeyup={test}\n        onBlur={test}\n        {...spread}\n      />,\n      container,\n    );\n    const input = container.querySelector('#test');\n    expect(obj.click).toHaveBeenCalledTimes(0);\n    expect(obj.ref).toHaveBeenCalledTimes(1); // Verify hook works\n    input.click();\n    setTimeout(() => {\n      expect(obj.click).toHaveBeenCalledTimes(1); // Verify hook works\n      done();\n    }, 25);\n  });\n\n  describe('should correctly handle VNodes as quasi-immutable objects, like ReactElement does', () => {\n    const a = <div>Hello world</div>;\n    const b = <span>This works!</span>;\n    const C = ({ children }) => {\n      return (\n        <div>\n          {children}\n          {children}\n          {children}\n        </div>\n      );\n    };\n\n    it('basic example ', () => {\n      render(a, container);\n      expect(container.innerHTML).toBe('<div>Hello world</div>');\n      render(b, container);\n      expect(container.innerHTML).toBe('<span>This works!</span>');\n    });\n\n    it('basic example #2 ', () => {\n      render(<div>{[a, a, a]}</div>, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>Hello world</div><div>Hello world</div><div>Hello world</div></div>',\n      );\n      render(b, container);\n      expect(container.innerHTML).toBe('<span>This works!</span>');\n    });\n\n    it('basic nested example ', () => {\n      render(\n        <div>\n          {a}\n          {b}\n        </div>,\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div><div>Hello world</div><span>This works!</span></div>',\n      );\n      render(\n        <div>\n          {b}\n          {a}\n        </div>,\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div><span>This works!</span><div>Hello world</div></div>',\n      );\n    });\n\n    it('basic nested component example ', () => {\n      render(<C>{a}</C>, container);\n      expect(container.innerHTML).toBe(\n        '<div><div>Hello world</div><div>Hello world</div><div>Hello world</div></div>',\n      );\n      render(\n        <C>\n          {b}\n          {a}\n        </C>,\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div><span>This works!</span><div>Hello world</div><span>This works!</span><div>Hello world</div><span>This works!</span><div>Hello world</div></div>',\n      );\n    });\n  });\n\n  describe('should correctly handle TEXT VNodes as quasi-immutable objects, like ReactElement does', () => {\n    const a = createVNode(VNodeFlags.Text, null, null, 'Hello world');\n    const b = createVNode(VNodeFlags.Text, null, null, 'This works!');\n    const C = ({ children }) => (\n      <div>\n        {children}\n        {children}\n        {children}\n      </div>\n    );\n\n    it('basic example ', () => {\n      render(a, container);\n      expect(container.innerHTML).toBe('Hello world');\n      render(b, container);\n      expect(container.innerHTML).toBe('This works!');\n    });\n\n    it('basic example #2 ', () => {\n      render(<div>{[a, a, a]}</div>, container);\n      expect(container.innerHTML).toBe(\n        '<div>Hello worldHello worldHello world</div>',\n      );\n      render(b, container);\n      expect(container.innerHTML).toBe('This works!');\n    });\n\n    it('basic nested example ', () => {\n      render(\n        <div>\n          {a}\n          {b}\n        </div>,\n        container,\n      );\n      expect(container.innerHTML).toBe('<div>Hello worldThis works!</div>');\n      render(\n        <div>\n          {b}\n          {a}\n        </div>,\n        container,\n      );\n      expect(container.innerHTML).toBe('<div>This works!Hello world</div>');\n    });\n\n    it('basic nested component example #2 ', () => {\n      render(<C>{a}</C>, container);\n      expect(container.innerHTML).toBe(\n        '<div>Hello worldHello worldHello world</div>',\n      );\n      render(\n        <C>\n          {b}\n          {a}\n        </C>,\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div>This works!Hello worldThis works!Hello worldThis works!Hello world</div>',\n      );\n    });\n  });\n\n  describe('should properly render multiline text via JSX', () => {\n    it('should render accordingly', () => {\n      render(\n        <div class=\"tesla-battery__notice\">\n          <p>\n            The actual amount of range that you experience will vary based on\n            your particular use conditions. See how particular use conditions\n            may affect your range in our simulation model.\n          </p>\n          <p>\n            Vehicle range may vary depending on the vehicle configuration,\n            battery age and condition, driving style and operating,\n            environmental and climate conditions.\n          </p>\n        </div>,\n        container,\n      );\n      expect(container.innerHTML).toBe(\n        '<div class=\"tesla-battery__notice\"><p>The actual amount of range that you experience will vary based on your particular use conditions. See how particular use conditions may affect your range in our simulation model.</p><p>Vehicle range may vary depending on the vehicle configuration, battery age and condition, driving style and operating, environmental and climate conditions.</p></div>',\n      );\n    });\n  });\n\n  describe('REST Spread JSX', () => {\n    it('Should render click event, style, className', (done) => {\n      const TextField = function (props) {\n        return <input {...props} />;\n      };\n      const MyTextField = ({ name, className, changeName }) => (\n        <TextField\n          className={className}\n          value={name}\n          onClick={function () {\n            done();\n          }}\n        />\n      );\n\n      render(<MyTextField className=\"foobar\" name=\"test\" />, container);\n\n      expect(container.firstChild.value).toBe('test');\n      expect(container.firstChild.getAttribute('class')).toBe('foobar');\n      container.firstChild.click();\n    });\n  });\n\n  if (\n    typeof global !== 'undefined' &&\n    !global.usingJSDOM &&\n    'position' in document.createElement('progress')\n  ) {\n    describe('Progress element', () => {\n      it('Should be possible to change value of Progress element Github#714', () => {\n        render(<progress max={100} value=\"10\" />, container);\n\n        expect(container.firstChild.getAttribute('value')).toEqual('10');\n\n        render(<progress max={100} value=\"33\" />, container);\n\n        expect(container.firstChild.getAttribute('value')).toEqual('33');\n\n        render(<progress max={100} value={'0'} />, container);\n\n        expect(container.firstChild.getAttribute('value')).toEqual('0');\n      });\n      it('Should be possible to render Progress element without value', () => {\n        render(<progress max={100} />, container);\n        expect(container.firstChild.tagName).toEqual('PROGRESS');\n        expect([null, '', 0, '0']).toContain(\n          container.firstChild.getAttribute('value'),\n        );\n\n        // Add as string\n        render(<progress max={100} value=\"3\" />, container);\n        expect(container.firstChild.tagName).toEqual('PROGRESS');\n        expect(container.firstChild.getAttribute('value')).toEqual('3');\n      });\n    });\n  }\n\n  describe('Value for components', () => {\n    it('Should be possible to pass down value prop', () => {\n      function Foo({ value }) {\n        return <div>{value}</div>;\n      }\n\n      render(<Foo value=\"100\" />, container);\n\n      expect(container.innerHTML).toEqual('<div>100</div>');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/events.spec.js",
    "content": "import { render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('Basic event tests', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should attach basic click events', (done) => {\n    const template = (val) =>\n      createElement('div', {\n        id: 'test',\n        onclick: val,\n      });\n\n    let calledFirstTest = false;\n\n    function test() {\n      calledFirstTest = true;\n    }\n\n    // different event\n    let calledSecondTest = false;\n\n    function test2() {\n      calledSecondTest = true;\n    }\n\n    render(template(test), container);\n\n    let divs = container.querySelectorAll('div');\n    for (const div of divs) {\n      div.click();\n    }\n    expect(calledFirstTest).toBe(true);\n\n    // reset\n    calledFirstTest = false;\n\n    render(template(test2), container);\n    divs = container.querySelectorAll('div');\n    for (const div of divs) {\n      div.click();\n    }\n\n    expect(calledFirstTest).toBe(false);\n    expect(calledSecondTest).toBe(true);\n\n    // reset\n    calledFirstTest = false;\n    calledSecondTest = false;\n\n    render(null, container);\n    divs = container.querySelectorAll('div');\n    for (const div of divs) {\n      div.click();\n    }\n\n    expect(calledFirstTest).toBe(false);\n    expect(calledSecondTest).toBe(false);\n    done();\n  });\n\n  it('should update events', () => {\n    let data = {\n      count: 0,\n    };\n\n    function onClick(d) {\n      return function (e) {\n        data = { count: d.count + 1 };\n\n        renderIt();\n      };\n    }\n\n    function App(d) {\n      return createElement(\n        'button',\n        {\n          onclick: onClick(d),\n        },\n        'Count ',\n        d.count,\n      );\n    }\n\n    function renderIt() {\n      render(App(data), container);\n    }\n\n    renderIt();\n    const buttons = container.querySelectorAll('button');\n\n    expect(container.firstChild.innerHTML).toBe('Count 0');\n    expect(data.count).toBe(0);\n    for (const button of buttons) {\n      button.click();\n    }\n    expect(container.firstChild.innerHTML).toBe('Count 1');\n    expect(data.count).toBe(1);\n    for (const button of buttons) {\n      button.click();\n    }\n    expect(container.firstChild.innerHTML).toBe('Count 2');\n    expect(data.count).toBe(2);\n  });\n\n  it('should not trigger click at all if target is disabled', () => {\n    let data = {\n      count: 0,\n    };\n\n    function onClick(d) {\n      return function (e) {\n        data = { count: d.count + 1 };\n\n        renderIt();\n      };\n    }\n\n    function App(d) {\n      return createElement(\n        'button',\n        {\n          disabled: 'disabled',\n          onClick: onClick(d),\n        },\n        createElement('span', null, 'Count ', d.count),\n      );\n    }\n\n    function renderIt() {\n      render(App(data), container);\n    }\n\n    renderIt();\n    const buttons = container.querySelectorAll('span');\n\n    expect(container.firstChild.innerHTML).toBe('<span>Count 0</span>');\n    expect(data.count).toBe(0);\n    for (const button of buttons) {\n      button.click();\n    }\n    expect(container.firstChild.innerHTML).toBe('<span>Count 0</span>');\n  });\n\n  it('should not leak memory', () => {\n    const eventHandler = function () {};\n\n    function AppTwo() {\n      return createElement('button', null, [2]);\n    }\n\n    function App() {\n      return createElement(\n        'button',\n        {\n          onsubmit: eventHandler,\n        },\n        ['1'],\n      );\n    }\n\n    render(App(), container);\n    expect(container.firstChild.innerHTML).toBe('1');\n\n    render(App(), container);\n    expect(container.firstChild.innerHTML).toBe('1');\n\n    render(AppTwo(), container);\n    expect(container.firstChild.innerHTML).toBe('2');\n  });\n\n  it('should not leak memory #2', () => {\n    const eventHandler = function () {};\n\n    function App({ toggle }) {\n      return createElement(\n        'button',\n        {\n          onsubmit: toggle ? eventHandler : null,\n        },\n        ['1'],\n      );\n    }\n\n    render(App({ toggle: true }), container);\n    expect(container.firstChild.innerHTML).toBe('1');\n\n    render(App({ toggle: false }), container);\n    expect(container.firstChild.innerHTML).toBe('1');\n  });\n\n  it('should not leak memory when child changes', () => {\n    const eventHandler = function () {};\n\n    function smallComponent() {\n      return createElement(\n        'div',\n        {\n          onkeyup: eventHandler,\n        },\n        '2',\n      );\n    }\n\n    const childrenArray = [\n      smallComponent(),\n      smallComponent(),\n      smallComponent(),\n    ];\n\n    function AppTwo() {\n      return createElement('p', null, ['2']);\n    }\n\n    function App(children) {\n      return createElement(\n        'p',\n        {\n          onkeydown: eventHandler,\n        },\n        children.slice(0),\n      );\n    }\n\n    render(App(childrenArray), container);\n    expect(container.innerHTML).toBe(\n      '<p><div>2</div><div>2</div><div>2</div></p>',\n    );\n\n    childrenArray.pop();\n\n    render(App(childrenArray), container);\n    expect(container.innerHTML).toBe('<p><div>2</div><div>2</div></p>');\n\n    render(AppTwo(), container);\n    expect(container.innerHTML).toBe('<p>2</p>');\n  });\n\n  describe('Event Propagation', () => {\n    it('Should stop propagating Synthetic event to document', (done) => {\n      const eventHandlerSpy = jasmine.createSpy('spy');\n      const eventHandler = function (event) {\n        eventHandlerSpy();\n        event.stopPropagation();\n      };\n\n      function SmallComponent() {\n        return createElement(\n          'div',\n          {\n            onClick: eventHandler,\n            id: 'tester',\n          },\n          '2',\n        );\n      }\n\n      render(<SmallComponent />, container);\n\n      const bodySpy = jasmine.createSpy('spy');\n      document.addEventListener('click', bodySpy);\n\n      container.querySelector('#tester').click();\n      setTimeout(function () {\n        expect(eventHandlerSpy.calls.count()).toBe(1);\n        expect(bodySpy.calls.count()).toBe(0);\n        document.removeEventListener('click', bodySpy);\n        done();\n      }, 20);\n    });\n\n    it('Should stop propagating Synthetic event to parentElement with synthetic event', (done) => {\n      const eventHandlerSpy = jasmine.createSpy('spy');\n      const eventHandler = function (event) {\n        eventHandlerSpy();\n        event.stopPropagation();\n      };\n\n      const eventHandlerSpy2 = jasmine.createSpy('spy');\n      const eventHandler2 = function (event) {\n        eventHandlerSpy2();\n      };\n\n      function SmallComponent() {\n        return createElement(\n          'div',\n          {\n            onClick: eventHandler2,\n            id: 'parent',\n          },\n          createElement(\n            'div',\n            {\n              onClick: eventHandler,\n              id: 'tester',\n            },\n            '2',\n          ),\n        );\n      }\n\n      render(<SmallComponent />, container);\n\n      container.querySelector('#tester').click();\n      setTimeout(function () {\n        expect(eventHandlerSpy.calls.count()).toBe(1);\n        expect(eventHandlerSpy2.calls.count()).toBe(0);\n        done();\n      }, 20);\n    });\n\n    // React does not block propagating synthetic event to parent with normal event either.\n    it('Should NOT stop propagating Synthetic event to parentElement with normal event', (done) => {\n      const eventHandlerSpy = jasmine.createSpy('spy');\n      const eventHandler = function (event) {\n        eventHandlerSpy();\n        event.stopPropagation();\n      };\n\n      const eventHandlerSpy2 = jasmine.createSpy('spy');\n      const eventHandler2 = function (event) {\n        eventHandlerSpy2();\n      };\n\n      function SmallComponent() {\n        return createElement(\n          'div',\n          {\n            onclick: eventHandler2,\n            id: 'parent',\n          },\n          createElement(\n            'div',\n            {\n              onClick: eventHandler,\n              id: 'tester',\n            },\n            '2',\n          ),\n        );\n      }\n\n      render(<SmallComponent />, container);\n\n      container.querySelector('#tester').click();\n      setTimeout(function () {\n        expect(eventHandlerSpy.calls.count()).toBe(1);\n        expect(eventHandlerSpy2.calls.count()).toBe(1);\n        done();\n      }, 20);\n    });\n\n    // https://github.com/infernojs/inferno/issues/979\n    it('Should trigger child elements synthetic event even if parent Element has null listener', () => {\n      const spy1 = jasmine.createSpy('spy');\n      const spy2 = jasmine.createSpy('spy');\n\n      function FooBarCom({ test }) {\n        return (\n          <div onClick={test !== '1' ? null : spy1}>\n            <div onClick={null}>\n              <span onClick={spy2}>test</span>\n            </div>\n          </div>\n        );\n      }\n\n      render(<FooBarCom test=\"1\" />, container);\n      container.querySelector('span').click();\n      expect(spy2.calls.count()).toBe(1);\n      expect(spy1.calls.count()).toBe(1);\n\n      render(<FooBarCom test=\"2\" />, container);\n      container.querySelector('span').click();\n      expect(spy2.calls.count()).toBe(2);\n      expect(spy1.calls.count()).toBe(1);\n\n      render(<FooBarCom test=\"3\" />, container);\n      container.querySelector('span').click();\n      expect(spy2.calls.count()).toBe(3);\n      expect(spy1.calls.count()).toBe(1);\n    });\n\n    it('Should remove synthetic listener if patched to null/undef', () => {\n      const spy1 = jasmine.createSpy('spy');\n      const spy2 = jasmine.createSpy('spy');\n\n      function FooBarCom({ test }) {\n        return (\n          <div>\n            {test ? (\n              <div onClick={spy1}>\n                <span onClick={spy2}>test</span>\n              </div>\n            ) : (\n              <div>\n                <span onClick={spy2}>test</span>\n              </div>\n            )}\n          </div>\n        );\n      }\n\n      render(<FooBarCom test={true} />, container);\n      container.querySelector('span').click();\n      expect(spy2.calls.count()).toBe(1);\n      expect(spy1.calls.count()).toBe(1);\n\n      render(<FooBarCom test={false} />, container);\n      container.querySelector('span').click();\n      expect(spy2.calls.count()).toBe(2);\n      expect(spy1.calls.count()).toBe(1);\n\n      render(<FooBarCom test={true} />, container);\n      container.querySelector('span').click();\n      expect(spy2.calls.count()).toBe(3);\n      expect(spy1.calls.count()).toBe(2);\n    });\n\n    it('Should remove native listener if patched to null/undef', () => {\n      const spy1 = jasmine.createSpy('spy');\n      const spy2 = jasmine.createSpy('spy');\n\n      function FooBarCom({ test }) {\n        return (\n          <div>\n            {test ? (\n              <div onclick={spy1}>\n                <span onclick={spy2}>test</span>\n              </div>\n            ) : (\n              <div>\n                <span onclick={spy2}>test</span>\n              </div>\n            )}\n          </div>\n        );\n      }\n\n      render(<FooBarCom test={true} />, container);\n      container.querySelector('span').click();\n      expect(spy2.calls.count()).toBe(1);\n      expect(spy1.calls.count()).toBe(1);\n\n      render(<FooBarCom test={false} />, container);\n      container.querySelector('span').click();\n      expect(spy2.calls.count()).toBe(2);\n      expect(spy1.calls.count()).toBe(1);\n\n      render(<FooBarCom test={true} />, container);\n      container.querySelector('span').click();\n      expect(spy2.calls.count()).toBe(3);\n      expect(spy1.calls.count()).toBe(2);\n    });\n\n    it('Should stop propagating normal event to document', () => {\n      const eventHandlerSpy = jasmine.createSpy('spy');\n      const eventHandler = function (event) {\n        eventHandlerSpy();\n        event.stopPropagation();\n      };\n\n      function SmallComponent() {\n        return createElement(\n          'div',\n          {\n            onclick: eventHandler,\n            id: 'tester',\n          },\n          '2',\n        );\n      }\n\n      render(<SmallComponent />, container);\n      const bodySpy = jasmine.createSpy('spy');\n      document.addEventListener('click', bodySpy);\n\n      container.querySelector('#tester').click();\n\n      expect(eventHandlerSpy.calls.count()).toBe(1);\n      expect(bodySpy.calls.count()).toBe(0);\n      document.removeEventListener('click', bodySpy);\n    });\n\n    it('Should stop propagating normal event to parentElement with synthetic event', (done) => {\n      const eventHandlerSpy = jasmine.createSpy('spy');\n      const eventHandler = function (event) {\n        eventHandlerSpy();\n        event.stopPropagation();\n      };\n\n      const eventHandlerSpy2 = jasmine.createSpy('spy');\n      const eventHandler2 = function (event) {\n        eventHandlerSpy2();\n      };\n\n      function SmallComponent() {\n        return createElement(\n          'div',\n          {\n            onClick: eventHandler2,\n            id: 'parent',\n          },\n          createElement(\n            'div',\n            {\n              onclick: eventHandler,\n              id: 'tester',\n            },\n            '2',\n          ),\n        );\n      }\n\n      render(<SmallComponent />, container);\n\n      container.querySelector('#tester').click();\n      setTimeout(function () {\n        expect(eventHandlerSpy.calls.count()).toBe(1);\n        expect(eventHandlerSpy2.calls.count()).toBe(0);\n        done();\n      }, 20);\n    });\n\n    it('Should stop propagating normal event to normal event', (done) => {\n      const eventHandlerSpy = jasmine.createSpy('spy');\n      const eventHandler = function (event) {\n        eventHandlerSpy();\n        event.stopPropagation();\n      };\n\n      const eventHandlerSpy2 = jasmine.createSpy('spy');\n      const eventHandler2 = function () {\n        eventHandlerSpy2();\n      };\n\n      function SmallComponent() {\n        return createElement(\n          'div',\n          {\n            onclick: eventHandler2,\n            id: 'parent',\n          },\n          createElement(\n            'div',\n            {\n              onclick: eventHandler,\n              id: 'tester',\n            },\n            '2',\n          ),\n        );\n      }\n\n      render(<SmallComponent />, container);\n\n      container.querySelector('#tester').click();\n      setTimeout(function () {\n        expect(eventHandlerSpy.calls.count()).toBe(1);\n        expect(eventHandlerSpy2.calls.count()).toBe(0);\n        done();\n      }, 20);\n    });\n  });\n\n  it('Should work with spread attributes', (done) => {\n    function SmallComponent(props) {\n      return (\n        <div id=\"testClick\" {...props}>\n          FooBar\n        </div>\n      );\n    }\n\n    const obj = {\n      test: function () {\n        done();\n      },\n    };\n\n    render(\n      <SmallComponent className=\"testing\" onClick={obj.test} />,\n      container,\n    );\n\n    container.querySelector('#testClick').click();\n  });\n\n  it('Synthetic Events - Should not reduce listener count when nothing was removed', () => {\n    const spy = jasmine.createSpy('spy');\n    const root1 = document.createElement('div');\n    const root2 = document.createElement('div');\n    const root3 = document.createElement('div');\n    const root4 = document.createElement('div');\n\n    document.body.appendChild(root1);\n    document.body.appendChild(root2);\n    document.body.appendChild(root3);\n    document.body.appendChild(root4);\n\n    render(<div onClick={spy} />, root1);\n    render(<div onClick={undefined} />, root2);\n    render(<div onClick={void 0} />, root3);\n    render(<div onClick={null} />, root4);\n\n    root1.firstChild.click();\n    root2.firstChild.click();\n    root3.firstChild.click();\n    root4.firstChild.click();\n\n    expect(spy.calls.count()).toBe(1);\n\n    render(null, root1);\n    render(null, root2);\n    render(null, root3);\n    render(null, root4);\n\n    document.body.removeChild(root1);\n    document.body.removeChild(root2);\n    document.body.removeChild(root3);\n    document.body.removeChild(root4);\n  });\n\n  describe('currentTarget', () => {\n    it('Should have currentTarget', (done) => {\n      function verifyCurrentTarget(event) {\n        expect(event.currentTarget).toBe(container.firstChild);\n        done();\n      }\n\n      render(<div onClick={verifyCurrentTarget} />, container);\n\n      container.firstChild.click();\n    });\n\n    it('Current target should not be the clicked element, but the one with listener', () => {\n      let called = false;\n\n      function verifyCurrentTarget(event) {\n        expect(event.currentTarget).toBe(container.firstChild);\n        called = true;\n      }\n\n      render(\n        <div onClick={verifyCurrentTarget}>\n          <span>test</span>\n        </div>,\n        container,\n      );\n\n      container.querySelector('span').click();\n\n      expect(called).toBe(true);\n    });\n\n    it('Should work with deeply nested tree', (done) => {\n      function verifyCurrentTarget(event) {\n        expect(event.currentTarget).toBe(container.querySelector('#test'));\n        done();\n      }\n\n      render(\n        <div>\n          <div>\n            <div>\n              <div>\n                <div>1</div>\n                <div id=\"test\" onClick={verifyCurrentTarget}>\n                  <div>foo</div>\n                  <span>2</span>\n                </div>\n              </div>\n            </div>\n          </div>\n          <span>test</span>\n        </div>,\n        container,\n      );\n\n      container.querySelector('span').click();\n    });\n\n    it('currentTarget should propagate work with multiple levels of children', (done) => {\n      function verifyCurrentTarget(event) {\n        expect(event.currentTarget).toBe(container.querySelector('#test'));\n        done();\n      }\n\n      render(\n        <div>\n          <div>\n            <div>\n              <div>\n                <div>1</div>\n                <div id=\"test\" onClick={verifyCurrentTarget}>\n                  <div>foo</div>\n                  <div>\n                    <div>\n                      <div>\n                        <div>\n                          <span>test</span>\n                        </div>\n                      </div>\n                    </div>\n                  </div>\n                  <div>1</div>\n                </div>\n              </div>\n            </div>\n          </div>\n          <span>test</span>\n        </div>,\n        container,\n      );\n\n      container.querySelector('span').click();\n    });\n  });\n\n  describe('Event removal', () => {\n    it('Should remove events when parent changes', () => {\n      const spy = jasmine.createSpy('spy');\n      render(\n        <div>\n          <div id=\"test\" onClick={spy}>\n            1\n          </div>\n        </div>,\n        container,\n      );\n\n      expect(spy.calls.count()).toBe(0);\n      container.querySelector('#test').click();\n      expect(spy.calls.count()).toBe(1);\n\n      render(\n        <div>\n          <div id=\"test\">2</div>\n        </div>,\n        container,\n      );\n\n      container.querySelector('#test').click();\n      expect(spy.calls.count()).toBe(1);\n    });\n\n    it('Should NOT remove events when listener remains there', () => {\n      const spy = jasmine.createSpy('spy');\n      render(\n        <div>\n          <div id=\"test\" onClick={spy}>\n            1\n          </div>\n        </div>,\n        container,\n      );\n\n      expect(spy.calls.count()).toBe(0);\n      container.querySelector('#test').click();\n      expect(spy.calls.count()).toBe(1);\n\n      render(\n        <div>\n          <div id=\"test\" onClick={spy}>\n            2\n          </div>\n        </div>,\n        container,\n      );\n\n      container.querySelector('#test').click();\n      expect(spy.calls.count()).toBe(2);\n    });\n\n    it('Should remove events when listener is nulled', () => {\n      const spy = jasmine.createSpy('spy');\n      render(\n        <div>\n          <div id=\"test\" onClick={spy}>\n            1\n          </div>\n        </div>,\n        container,\n      );\n\n      expect(spy.calls.count()).toBe(0);\n      container.querySelector('#test').click();\n      expect(spy.calls.count()).toBe(1);\n\n      render(\n        <div>\n          <div id=\"test\" onClick={null}>\n            2\n          </div>\n        </div>,\n        container,\n      );\n\n      container.querySelector('#test').click();\n      expect(spy.calls.count()).toBe(1);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/hooks.spec.js",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('lifecycle hooks', () => {\n  describe('Stateless component hooks', () => {\n    let template;\n    let container;\n    let animationTemplate;\n\n    function StatelessComponent() {\n      const divTemplate = () => {\n        return createElement('div', null, 'Hello world!');\n      };\n      return divTemplate();\n    }\n\n    afterEach(function () {\n      render(null, container);\n    });\n\n    beforeEach(function () {\n      container = document.createElement('div');\n\n      template =\n        (\n          onComponentWillMount,\n          onComponentDidMount,\n          onComponentWillUnmount,\n          onComponentWillUpdate,\n          onComponentDidUpdate,\n          onComponentShouldUpdate,\n          StatelessComponent,\n        ) =>\n        (props) => {\n          return createElement(\n            StatelessComponent,\n            {\n              onComponentWillMount,\n              onComponentDidMount,\n              onComponentWillUnmount,\n              onComponentWillUpdate,\n              onComponentDidUpdate,\n              onComponentShouldUpdate,\n              ...props,\n            },\n            null,\n          );\n        };\n\n      animationTemplate =\n        (onComponentDidAppear, onComponentWillDisappear, StatelessComponent) =>\n        (props) => {\n          return createElement(\n            StatelessComponent,\n            {\n              onComponentDidAppear,\n              onComponentWillDisappear,\n              ...props,\n            },\n            null,\n          );\n        };\n    });\n\n    it('\"onComponentWillMount\" hook should fire, args props', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      const node = template(\n        spyObj.fn,\n        null,\n        null,\n        null,\n        null,\n        null,\n        StatelessComponent,\n      )({ a: 1 });\n      render(node, container);\n\n      expect(spy.calls.count()).toBe(1);\n      expect(spy.calls.argsFor(0).length).toBe(1);\n      expect(spy.calls.argsFor(0)[0]).toEqual({ a: 1, children: null });\n    });\n\n    it('\"onComponentDidMount\" hook should fire, args DOM props', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      const node = template(\n        null,\n        spyObj.fn,\n        null,\n        null,\n        null,\n        null,\n        StatelessComponent,\n      )({ a: 1 });\n      render(node, container);\n\n      expect(spy.calls.count()).toBe(1);\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0]).toBe(container.firstChild);\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 1, children: null });\n    });\n\n    it('\"onComponentWillUnmount\" hook should fire, args DOM props', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      const node = template(\n        null,\n        null,\n        spyObj.fn,\n        null,\n        null,\n        null,\n        StatelessComponent,\n      )({ a: 1 });\n      render(node, container);\n      expect(spy.calls.count()).toBe(0);\n      // do unmount\n      render(null, container);\n\n      expect(spy.calls.count()).toBe(1);\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0].outerHTML).toBe('<div>Hello world!</div>');\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 1, children: null });\n    });\n\n    it('\"onComponentWillUpdate\" hook should fire, args props nextProps', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      const t = template(\n        null,\n        null,\n        null,\n        spyObj.fn,\n        null,\n        null,\n        StatelessComponent,\n      );\n\n      const node1 = t({ a: 1 });\n      render(node1, container);\n      expect(spy.calls.count()).toBe(0);\n\n      const node2 = t({ a: 2 });\n      render(node2, container);\n      expect(spy.calls.count()).toBe(1);\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0]).toEqual({ a: 1, children: null });\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 2, children: null });\n    });\n\n    it('\"onComponentDidUpdate\" hook should fire, args prevProps props', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      const t = template(\n        null,\n        null,\n        null,\n        null,\n        spyObj.fn,\n        null,\n        StatelessComponent,\n      );\n\n      const node1 = t({ a: 1 });\n      render(node1, container);\n      expect(spy.calls.count()).toBe(0); // Update 1\n\n      const node2 = t({ a: 2 });\n      render(node2, container);\n      expect(spy.calls.count()).toBe(1); // Update 2\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0]).toEqual({ a: 1, children: null });\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 2, children: null });\n    });\n\n    it('\"onComponentShouldUpdate\" hook should fire, should call render when return true, args props nextProps', () => {\n      let onComponentShouldUpdateCount = 0;\n      let renderCount = 0;\n      const spyObj = {\n        fn: () => {\n          onComponentShouldUpdateCount++;\n          return true;\n        },\n      };\n      const spy = spyOn(spyObj, 'fn').and.callThrough();\n      const StatelessComponent = () => {\n        renderCount++;\n        return null;\n      };\n      const t = template(\n        null,\n        null,\n        null,\n        null,\n        null,\n        spyObj.fn,\n        StatelessComponent,\n      );\n\n      const node1 = t({ a: 1 });\n      render(node1, container);\n      expect(onComponentShouldUpdateCount).toBe(0); // Update 1\n      expect(renderCount).toBe(1); // Rendered 1 time\n\n      const node2 = t({ a: 2 });\n      render(node2, container);\n      expect(onComponentShouldUpdateCount).toBe(1); // Update 2\n      expect(renderCount).toBe(2); // Rendered 2 time\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0]).toEqual({ a: 1, children: null });\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 2, children: null });\n    });\n\n    it('\"onComponentShouldUpdate\" hook should fire, should not call render when return false, args props nextProps', () => {\n      let onComponentShouldUpdateCount = 0;\n      let renderCount = 0;\n      const spyObj = {\n        fn: () => {\n          onComponentShouldUpdateCount++;\n          return false;\n        },\n      };\n      const spy = spyOn(spyObj, 'fn').and.callThrough();\n      const StatelessComponent = () => {\n        renderCount++;\n        return null;\n      };\n      const t = template(\n        null,\n        null,\n        null,\n        null,\n        null,\n        spyObj.fn,\n        StatelessComponent,\n      );\n\n      const node1 = t({ a: 1 });\n      render(node1, container);\n      expect(onComponentShouldUpdateCount).toBe(0); // Update 1\n      expect(renderCount).toBe(1); // Rendered 1 time\n\n      const node2 = t({ a: 2 });\n      render(node2, container);\n      expect(onComponentShouldUpdateCount).toBe(1); // Update 2\n      expect(renderCount).toBe(1); // Rendered 1 time\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0]).toEqual({ a: 1, children: null });\n      expect(spy.calls.argsFor(0)[1]).toEqual({ a: 2, children: null });\n    });\n\n    it('\"onComponentDidAppear\" hook should fire, args dom props', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n\n      const spy = spyOn(spyObj, 'fn');\n      const t = animationTemplate(spyObj.fn, null, StatelessComponent);\n\n      const node1 = t({ a: 1 });\n      render(node1, container);\n      expect(spy.calls.count()).toBe(1); // Update 1\n      expect(spy.calls.argsFor(0).length).toBe(2);\n      expect(spy.calls.argsFor(0)[0] instanceof HTMLDivElement).toEqual(true);\n      expect(typeof spy.calls.argsFor(0)[1] === 'object').toEqual(true);\n\n      const node2 = t({ a: 2 });\n      render(node2, container);\n      expect(spy.calls.count()).toBe(1); // Update 2 (shouldn't trigger animation)\n    });\n\n    it('\"onComponentWillDisappear\" hook should fire, args dom props', () => {\n      const spyObj = {\n        fn: () => {},\n      };\n\n      const spy = spyOn(spyObj, 'fn');\n      const t = animationTemplate(null, spyObj.fn, StatelessComponent);\n\n      const node1 = t({ a: 1 });\n      render(node1, container);\n      render(null, container);\n\n      expect(spy.calls.count()).toBe(1); // animation triggers on remove\n      expect(spy.calls.argsFor(0).length).toBe(3);\n      expect(spy.calls.argsFor(0)[0] instanceof HTMLDivElement).toEqual(true);\n      expect(typeof spy.calls.argsFor(0)[1] === 'object').toEqual(true);\n      expect(typeof spy.calls.argsFor(0)[2] === 'function').toEqual(true);\n    });\n  });\n\n  describe('Class Component hooks', function () {\n    it('Should trigger ref callback when component is mounting and unmounting', () => {\n      const container = document.createElement('div');\n      class FooBar extends Component {\n        render() {\n          return createElement('div');\n        }\n      }\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      const node = createElement(FooBar, { ref: spyObj.fn });\n\n      render(node, container);\n\n      expect(spy.calls.count()).toBe(1);\n      expect(spy.calls.argsFor(0).length).toBe(1);\n      expect(spy.calls.argsFor(0)[0]).not.toEqual(null);\n\n      render(null, container);\n\n      expect(spy.calls.count()).toBe(2);\n      expect(spy.calls.argsFor(1).length).toBe(1);\n      expect(spy.calls.argsFor(1)[0]).toEqual(null);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/patchKeyedChildren.spec.js",
    "content": "import { createTextVNode, createVNode, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\n\nfunction generateKeyNodes(array) {\n  let i, id, key;\n  const children = [];\n  let newKey;\n\n  for (i = 0; i < array.length; i++) {\n    id = key = array[i];\n    if (key !== null && (typeof key !== 'string' || key[0] !== '#')) {\n      newKey = key;\n    } else {\n      newKey = null;\n    }\n\n    children.push(\n      createElement(\n        'div',\n        {\n          key: newKey,\n          id: String(id),\n        },\n        id,\n      ),\n    );\n  }\n  return children;\n}\n\ndescribe('keyed-nodes', () => {\n  let container;\n\n  const template = function (child) {\n    return createElement('div', null, child);\n  };\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should add all nodes', () => {\n    render(template(generateKeyNodes([])), container);\n    render(template(generateKeyNodes(['#0', '#1', '#2', '#3'])), container);\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should remove two keys at the beginning', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['c'])), container);\n    expect(container.textContent).toBe('c');\n    expect(container.firstChild.childNodes.length).toBe(1);\n  });\n  it('should size up', () => {\n    render(template(generateKeyNodes(['#0', '#1'])), container);\n    render(template(generateKeyNodes(['#0', '#1', '#2', '#3'])), container);\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should size down', () => {\n    render(template(generateKeyNodes(['#0', '#1', '#2', '#3'])), container);\n    render(template(generateKeyNodes(['#0', '#1'])), container);\n    expect(container.textContent).toBe('#0#1');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    render(template(generateKeyNodes(['#0', '#1', '#2', '#3'])), container);\n    render(template(generateKeyNodes(['#0', '#1'])), container);\n    expect(container.textContent).toBe('#0#1');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n\n  it('should clear all nodes', () => {\n    render(template(generateKeyNodes(['#0', '#1', '#2', '#3'])), container);\n    render(template(generateKeyNodes([])), container);\n    expect(container.textContent).toBe('');\n    expect(container.firstChild.childNodes.length).toBe(0);\n    render(template(generateKeyNodes(['#0', '#1', '#2', '#3'])), container);\n    render(template(generateKeyNodes([])), container);\n  });\n\n  it('should work with mixed nodes', () => {\n    render(template(generateKeyNodes(['1', '#0', '#1', '#2'])), container);\n    render(template(generateKeyNodes(['#0', '#1', '#2', '#3'])), container);\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key for start to end', () => {\n    render(template(generateKeyNodes(['a', '#0', '#1', '#2'])), container);\n    render(template(generateKeyNodes(['#0', '#1', '#2', 'a'])), container);\n    expect(container.textContent).toBe('#0#1#2a');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key', () => {\n    render(template(generateKeyNodes(['#0', 'a', '#2', '#3'])), container);\n    render(template(generateKeyNodes(['#0', '#1', 'a', '#3'])), container);\n    expect(container.textContent).toBe('#0#1a#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key with a size up', () => {\n    render(template(generateKeyNodes(['a', '#1', '#2', '#3'])), container);\n    render(\n      template(generateKeyNodes(['#0', '#1', '#2', '#3', 'a', '#5'])),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3a#5');\n    expect(container.firstChild.childNodes.length).toBe(6);\n  });\n  it('should move a key with a size down', () => {\n    render(template(generateKeyNodes(['a', '#1', '#2', '#3'])), container);\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    expect(container.textContent).toBe('#0a#2');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should avoid unnecessary reordering', () => {\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    expect(container.textContent).toBe('#0a#2');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should work with keyed nodes', () => {\n    render(template(generateKeyNodes([0, 1, 2, 3, 4])), container);\n    render(template(generateKeyNodes([1, 2, 3, 4, 0])), container);\n    expect(container.textContent).toBe('12340');\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([0, 1, 2, 3, 4])), container);\n    expect(container.textContent).toBe('01234');\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n    render(template(generateKeyNodes(['#0', 'a', '#2'])), container);\n    expect(container.textContent).toBe('#0a#2');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should reorder keys', () => {\n    render(\n      template(generateKeyNodes(['1', '2', '3', '4', 'abc', '6', 'def', '7'])),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n  });\n  it('should remove one key at the start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['b', 'c'])), container);\n    expect(container.textContent).toBe('bc');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should do a complex reverse', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    render(template(generateKeyNodes(['d', 'c', 'b', 'a'])), container);\n    expect(container.textContent).toBe('dcba');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should remove two keys at the start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['c'])), container);\n    expect(container.textContent).toBe('c');\n    expect(container.firstChild.childNodes.length).toBe(1);\n  });\n  it('should add one key to start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes(['a', 'b'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should add two key to start', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes(['c'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should remove one key at the end', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['a', 'b'])), container);\n    expect(container.textContent).toBe('ab');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should remove two keys at the end', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    render(template(generateKeyNodes(['a'])), container);\n    expect(container.textContent).toBe('a');\n    expect(container.firstChild.childNodes.length).toBe(1);\n  });\n  it('should add one key at the end', () => {\n    render(template(generateKeyNodes(['a', 'b'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should add two key at the end', () => {\n    render(template(generateKeyNodes(['a'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should add to end, delete from center & reverse', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    render(template(generateKeyNodes(['e', 'd', 'c', 'a'])), container);\n    expect(container.textContent).toBe('edca');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should add to the beginning and remove', () => {\n    render(template(generateKeyNodes(['c', 'd'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'c', 'e'])), container);\n    expect(container.textContent).toBe('abce');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should keep a central pivot', () => {\n    render(template(generateKeyNodes(['1', '2', '3'])), container);\n    render(template(generateKeyNodes(['4', '2', '5'])), container);\n    expect(container.textContent).toBe('425');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should insert to the middle', () => {\n    render(template(generateKeyNodes(['c', 'd', 'e'])), container);\n    render(template(generateKeyNodes(['a', 'b', 'e'])), container);\n    expect(container.textContent).toBe('abe');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes(['c', 'd', 'e'])), container);\n    render(template(generateKeyNodes(['c', 'd', 'e'])), container);\n    render(template(generateKeyNodes(['a', 'p', 'e'])), container);\n    expect(container.textContent).toBe('ape');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should shuffle, insert and remove', () => {\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 'e', 'f', 'g'])),\n      container,\n    );\n    render(template(generateKeyNodes(['b', 'c', 'a'])), container);\n    expect(container.textContent).toBe('bca');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should remove a element from the middle', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([1, 2, 4, 5])), container);\n    expect(container.textContent).toBe('1245');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a element forward', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([2, 3, 1, 4])), container);\n    expect(container.textContent).toBe('2314');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([3, 2, 1, 4])), container);\n    expect(container.textContent).toBe('3214');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([3, 2, 4, 1])), container);\n    expect(container.textContent).toBe('3241');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  it('should move a element to the end', () => {\n    render(template(generateKeyNodes([1, 2, 3])), container);\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes([2, 3, 1])), container);\n    expect(container.textContent).toBe('231');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should move a element backwards', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([1, 4, 2, 3])), container);\n    expect(container.textContent).toBe('1423');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should swap first and last', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([4, 2, 3, 1])), container);\n    expect(container.textContent).toBe('4231');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  it('should move to left and replace', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([4, 1, 2, 3, 6])), container);\n    expect(container.textContent).toBe('41236');\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateKeyNodes([4, 5, 2, 3, 0])), container);\n    expect(container.textContent).toBe('45230');\n    render(template(generateKeyNodes([1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(5);\n  });\n\n  it('should move to left and leave a hole', () => {\n    render(template(generateKeyNodes([1, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateKeyNodes([4, 6])), container);\n    expect(container.textContent).toBe('46');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should do something', () => {\n    render(template(generateKeyNodes([0, 1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(6);\n    render(template(generateKeyNodes([4, 3, 2, 1, 5, 0])), container);\n    expect(container.textContent).toBe('432150');\n    expect(container.firstChild.childNodes.length).toBe(6);\n  });\n\n  it('should cycle order correctly', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n    render(template(generateKeyNodes([2, 3, 4, 1])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('2341');\n    render(template(generateKeyNodes([3, 4, 1, 2])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('3412');\n    render(template(generateKeyNodes([4, 1, 2, 3])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('4123');\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n  });\n\n  it('should cycle order correctly in the other direction', () => {\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n    render(template(generateKeyNodes([4, 1, 2, 3])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('4123');\n    render(template(generateKeyNodes([3, 4, 1, 2])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('3412');\n    render(template(generateKeyNodes([2, 3, 4, 1])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('2341');\n    render(template(generateKeyNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    expect(container.textContent).toBe('1234');\n  });\n\n  it('should allow any character as a key', () => {\n    render(template(generateKeyNodes(['<WEIRD/&\\\\key>'])), container);\n    render(\n      template(\n        generateKeyNodes([\n          'INSANE/(/&\\\\key',\n          '<CRAZY/&\\\\key>',\n          '<WEIRD/&\\\\key>',\n        ]),\n      ),\n      container,\n    );\n    expect(container.textContent).toBe(\n      'INSANE/(/&\\\\key<CRAZY/&\\\\key><WEIRD/&\\\\key>',\n    );\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n\n  it('should reorder nodes', () => {\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n    render(\n      template(generateKeyNodes(['1', '2', '3', '4', 'abc', '6', 'def', '7'])),\n      container,\n    );\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n    render(\n      template(generateKeyNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n  });\n\n  it('should do a advanced shuffle - numbers and letters', () => {\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 1, 2, 3])),\n      container,\n    );\n    expect(container.textContent).toBe('abcd123');\n    expect(container.firstChild.childNodes.length).toBe(7);\n    render(\n      template(generateKeyNodes([1, 'e', 2, 'b', 'f', 'g', 'c', 'a', 3])),\n      container,\n    );\n    expect(container.textContent).toBe('1e2bfgca3');\n    expect(container.firstChild.childNodes.length).toBe(9);\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 1, 2, 3])),\n      container,\n    );\n    expect(container.textContent).toBe('abcd123');\n    expect(container.firstChild.childNodes.length).toBe(7);\n    render(\n      template(generateKeyNodes([0, 'e', 2, 'b', 'f', 'g', 'c', 'a', 4])),\n      container,\n    );\n    expect(container.textContent).toBe('0e2bfgca4');\n    expect(container.firstChild.childNodes.length).toBe(9);\n    render(\n      template(generateKeyNodes(['a', 'b', 'c', 'd', 1, 2, 3])),\n      container,\n    );\n    expect(container.textContent).toBe('abcd123');\n    expect(container.firstChild.childNodes.length).toBe(7);\n    render(\n      template(generateKeyNodes([1, 'e', 2, 'b', 'f', 'g', 'c', 'a', 3])),\n      container,\n    );\n    expect(container.textContent).toBe('1e2bfgca3');\n    expect(container.firstChild.childNodes.length).toBe(9);\n  });\n\n  it('should do a complex removal at the beginning', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes(['c', 'd'])), container);\n    expect(container.textContent).toBe('cd');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  it('should do move and sync nodes from right to left', () => {\n    render(template(generateKeyNodes(['a', 'b', 'c', 'd'])), container);\n    expect(container.textContent).toBe('abcd');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template(\n        generateKeyNodes(['c', 'l', 1, 2, 3, 4, 5, 6, 7, 8, 9, 'd', 'g', 'b']),\n      ),\n      container,\n    );\n    expect(container.textContent).toBe('cl123456789dgb');\n    expect(container.firstChild.childNodes.length).toBe(14);\n  });\n\n  describe('Should handle massive large arrays', () => {\n    let items;\n\n    beforeEach(function () {\n      items = new Array(1000);\n      for (let i = 0; i < 1000; i++) {\n        items[i] = i;\n      }\n    });\n\n    it('Should handle massive large arrays - initial', () => {\n      render(template(generateKeyNodes(items)), container);\n\n      expect(container.textContent).toEqual(items.join(''));\n    });\n\n    it('Should handle massive arrays shifting once by 2', () => {\n      items = items.concat(items.splice(0, 2));\n      render(template(generateKeyNodes(items)), container);\n\n      expect(container.textContent).toEqual(items.join(''));\n    });\n\n    for (let i = 0; i < 10; i++) {\n      it(\n        'Should handle massive arrays shifting ' + i + ' times by ' + i,\n        () => {\n          for (let j = 0; j < i; j++) {\n            items = items.concat(items.splice(i, j));\n          }\n          render(template(generateKeyNodes(items)), container);\n          expect(container.textContent).toEqual(items.join(''));\n        },\n      );\n    }\n  });\n\n  describe('Calendar like layout', () => {\n    function o(text) {\n      return createElement(\n        'span',\n        {\n          key: 'o' + text,\n        },\n        ',o' + text,\n      );\n    }\n\n    function d(text) {\n      return createElement(\n        'span',\n        {\n          key: 'd' + text,\n        },\n        ',d' + text,\n      );\n    }\n\n    function wk(text) {\n      return createElement(\n        'span',\n        {\n          key: 'wk' + text,\n        },\n        ',wk' + text,\n      );\n    }\n\n    it('Should do complex suffle without duplications', () => {\n      const layout1 = [\n        wk(31),\n        d(1),\n        d(2),\n        d(3),\n        d(4),\n        d(5),\n        d(6),\n        d(7),\n        wk(32),\n        d(8),\n        d(9),\n        d(10),\n        d(11),\n        d(12),\n        d(13),\n        d(14),\n        wk(33),\n        d(15),\n        d(16),\n        d(17),\n        d(18),\n        d(19),\n        d(20),\n        d(21),\n        wk(34),\n        d(22),\n        d(23),\n        d(24),\n        d(25),\n        d(26),\n        d(27),\n        d(28),\n        wk(35),\n        d(29),\n        d(30),\n        d(31),\n        o(1),\n        o(2),\n        o(3),\n        o(4),\n        wk(36),\n        o(5),\n        o(6),\n        o(7),\n        o(8),\n        o(9),\n        o(10),\n        o(11),\n      ];\n      render(template(layout1), container);\n\n      expect(container.textContent).toBe(\n        ',wk31,d1,d2,d3,d4,d5,d6,d7,wk32,d8,d9,d10,d11,d12,d13,d14,wk33,d15,d16,d17,d18,d19,d20,d21,wk34,d22,d23,d24,d25,d26,d27,d28,wk35,d29,d30,d31,o1,o2,o3,o4,wk36,o5,o6,o7,o8,o9,o10,o11',\n      );\n\n      const layout2 = [\n        wk(35),\n        o(29),\n        o(30),\n        o(31),\n        d(1),\n        d(2),\n        d(3),\n        d(4),\n        wk(36),\n        d(5),\n        d(6),\n        d(7),\n        d(8),\n        d(9),\n        d(10),\n        d(11),\n        wk(37),\n        d(12),\n        d(13),\n        d(14),\n        d(15),\n        d(16),\n        d(17),\n        d(18),\n        wk(38),\n        d(19),\n        d(20),\n        d(21),\n        d(22),\n        d(23),\n        d(24),\n        d(25),\n        wk(39),\n        d(26),\n        d(27),\n        d(28),\n        d(29),\n        d(30),\n        o(1),\n        o(2),\n        wk(40),\n        o(3),\n        o(4),\n        o(5),\n        o(6),\n        o(7),\n        o(8),\n        o(9),\n      ];\n      render(template(layout2), container);\n\n      expect(container.textContent).toBe(\n        ',wk35,o29,o30,o31,d1,d2,d3,d4,wk36,d5,d6,d7,d8,d9,d10,d11,wk37,d12,d13,d14,d15,d16,d17,d18,wk38,d19,d20,d21,d22,d23,d24,d25,wk39,d26,d27,d28,d29,d30,o1,o2,wk40,o3,o4,o5,o6,o7,o8,o9',\n      );\n    });\n  });\n\n  // VDom tests ported from Kivi - credits: https://github.com/localvoid\n  // https://github.com/localvoid/kivi/blob/master/tests/vdom.spec.ts\n  describe('children', () => {\n    const TESTS = [\n      [[0], [0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]],\n      [\n        [0, 1, 2],\n        [0, 1, 2],\n        [0, 0, 0, 0, 0, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n\n      [[], [1], [0, 0, 1, 0, 1, 0, 0], [0, 0, 1, 0, 1, 0, 0]],\n      [[], [4, 9], [0, 0, 2, 0, 2, 0, 0], [0, 0, 2, 0, 2, 0, 0]],\n      [[], [9, 3, 6, 1, 0], [0, 0, 5, 0, 5, 0, 0], [0, 0, 5, 0, 5, 0, 0]],\n\n      [[999], [1], [0, 0, 1, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0]],\n      [[999], [1, 999], [0, 0, 1, 0, 1, 0, 0], [0, 0, 1, 0, 1, 0, 0]],\n      [[999], [999, 1], [0, 0, 1, 0, 1, 0, 0], [0, 0, 1, 0, 1, 0, 0]],\n      [[999], [4, 9, 999], [0, 0, 2, 0, 2, 0, 0], [0, 0, 2, 0, 2, 0, 0]],\n      [[999], [999, 4, 9], [0, 0, 2, 0, 2, 0, 0], [0, 0, 2, 0, 2, 0, 0]],\n      [\n        [999],\n        [9, 3, 6, 1, 0, 999],\n        [0, 0, 5, 0, 5, 0, 0],\n        [0, 0, 5, 0, 5, 0, 0],\n      ],\n      [\n        [999],\n        [999, 9, 3, 6, 1, 0],\n        [0, 0, 5, 0, 5, 0, 0],\n        [0, 0, 5, 0, 5, 0, 0],\n      ],\n      [[999], [0, 999, 1], [0, 0, 2, 0, 2, 0, 0], [0, 0, 2, 0, 2, 0, 0]],\n      [[999], [0, 3, 999, 1, 4], [0, 0, 4, 0, 4, 0, 0], [0, 0, 4, 0, 4, 0, 0]],\n      [[999], [0, 999, 1, 4, 5], [0, 0, 4, 0, 4, 0, 0], [0, 0, 4, 0, 4, 0, 0]],\n\n      [\n        [998, 999],\n        [1, 998, 999],\n        [0, 0, 1, 0, 1, 0, 0],\n        [0, 0, 1, 0, 1, 0, 0],\n      ],\n      [\n        [998, 999],\n        [998, 999, 1],\n        [0, 0, 1, 0, 1, 0, 0],\n        [0, 0, 1, 0, 1, 0, 0],\n      ],\n      [\n        [998, 999],\n        [998, 1, 999],\n        [0, 0, 1, 0, 1, 0, 0],\n        [0, 0, 1, 0, 1, 0, 0],\n      ],\n      [\n        [998, 999],\n        [1, 2, 998, 999],\n        [0, 0, 2, 0, 2, 0, 0],\n        [0, 0, 2, 0, 2, 0, 0],\n      ],\n      [\n        [998, 999],\n        [998, 999, 1, 2],\n        [0, 0, 2, 0, 2, 0, 0],\n        [0, 0, 2, 0, 2, 0, 0],\n      ],\n      [\n        [998, 999],\n        [1, 998, 999, 2],\n        [0, 0, 2, 0, 2, 0, 0],\n        [0, 0, 2, 0, 2, 0, 0],\n      ],\n      [\n        [998, 999],\n        [1, 998, 2, 999, 3],\n        [0, 0, 3, 0, 3, 0, 0],\n        [0, 0, 3, 0, 3, 0, 0],\n      ],\n      [\n        [998, 999],\n        [1, 4, 998, 2, 5, 999, 3, 6],\n        [0, 0, 6, 0, 6, 0, 0],\n        [0, 0, 6, 0, 6, 0, 0],\n      ],\n      [\n        [998, 999],\n        [1, 998, 2, 999],\n        [0, 0, 2, 0, 2, 0, 0],\n        [0, 0, 2, 0, 2, 0, 0],\n      ],\n      [\n        [998, 999],\n        [998, 1, 999, 2],\n        [0, 0, 2, 0, 2, 0, 0],\n        [0, 0, 2, 0, 2, 0, 0],\n      ],\n      [\n        [998, 999],\n        [1, 2, 998, 3, 4, 999],\n        [0, 0, 4, 0, 4, 0, 0],\n        [0, 0, 4, 0, 4, 0, 0],\n      ],\n      [\n        [998, 999],\n        [998, 1, 2, 999, 3, 4],\n        [0, 0, 4, 0, 4, 0, 0],\n        [0, 0, 4, 0, 4, 0, 0],\n      ],\n      [\n        [998, 999],\n        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 998, 999],\n        [0, 0, 10, 0, 10, 0, 0],\n        [0, 0, 10, 0, 10, 0, 0],\n      ],\n      [\n        [998, 999],\n        [998, 999, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n        [0, 0, 10, 0, 10, 0, 0],\n        [0, 0, 10, 0, 10, 0, 0],\n      ],\n      [\n        [998, 999],\n        [0, 1, 2, 3, 4, 998, 999, 5, 6, 7, 8, 9],\n        [0, 0, 10, 0, 10, 0, 0],\n        [0, 0, 10, 0, 10, 0, 0],\n      ],\n      [\n        [998, 999],\n        [0, 1, 2, 998, 3, 4, 5, 6, 999, 7, 8, 9],\n        [0, 0, 10, 0, 10, 0, 0],\n        [0, 0, 10, 0, 10, 0, 0],\n      ],\n      [\n        [998, 999],\n        [0, 1, 2, 3, 4, 998, 5, 6, 7, 8, 9, 999],\n        [0, 0, 10, 0, 10, 0, 0],\n        [0, 0, 10, 0, 10, 0, 0],\n      ],\n      [\n        [998, 999],\n        [998, 0, 1, 2, 3, 4, 999, 5, 6, 7, 8, 9],\n        [0, 0, 10, 0, 10, 0, 0],\n        [0, 0, 10, 0, 10, 0, 0],\n      ],\n\n      [[1], [], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]],\n      [[1, 2], [2], [0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1]],\n      [[1, 2], [1], [0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1]],\n      [\n        [1, 2, 3],\n        [2, 3],\n        [0, 0, 0, 0, 0, 0, 1],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n      [\n        [1, 2, 3],\n        [1, 2],\n        [0, 0, 0, 0, 0, 0, 1],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n      [\n        [1, 2, 3],\n        [1, 3],\n        [0, 0, 0, 0, 0, 0, 1],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n      [\n        [1, 2, 3, 4, 5],\n        [2, 3, 4, 5],\n        [0, 0, 0, 0, 0, 0, 1],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n      [\n        [1, 2, 3, 4, 5],\n        [1, 2, 3, 4],\n        [0, 0, 0, 0, 0, 0, 1],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n      [\n        [1, 2, 3, 4, 5],\n        [1, 2, 4, 5],\n        [0, 0, 0, 0, 0, 0, 1],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n\n      [[1, 2], [], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]],\n      [[1, 2, 3], [3], [0, 0, 0, 0, 0, 0, 2], [0, 0, 0, 0, 0, 0, 2]],\n      [[1, 2, 3], [1], [0, 0, 0, 0, 0, 0, 2], [0, 0, 0, 0, 0, 0, 2]],\n      [\n        [1, 2, 3, 4],\n        [3, 4],\n        [0, 0, 0, 0, 0, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n      [\n        [1, 2, 3, 4],\n        [1, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n      [\n        [1, 2, 3, 4],\n        [1, 4],\n        [0, 0, 0, 0, 0, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n      [\n        [1, 2, 3, 4, 5, 6],\n        [2, 3, 4, 5],\n        [0, 0, 0, 0, 0, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n      [\n        [1, 2, 3, 4, 5, 6],\n        [2, 3, 5, 6],\n        [0, 0, 0, 0, 0, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n      [\n        [1, 2, 3, 4, 5, 6],\n        [1, 2, 3, 5],\n        [0, 0, 0, 0, 0, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n        [2, 3, 4, 5, 6, 7, 8, 9],\n        [0, 0, 0, 0, 0, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n        [0, 1, 2, 3, 4, 5, 6, 7],\n        [0, 0, 0, 0, 0, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n        [1, 2, 3, 4, 6, 7, 8, 9],\n        [0, 0, 0, 0, 0, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n        [0, 1, 2, 3, 4, 6, 7, 8],\n        [0, 0, 0, 0, 0, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n        [0, 1, 2, 4, 6, 7, 8, 9],\n        [0, 0, 0, 0, 0, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n\n      [\n        [0, 1],\n        [1, 0],\n        [0, 0, 0, 0, 1, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3],\n        [3, 2, 1, 0],\n        [0, 0, 0, 0, 3, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4],\n        [1, 2, 3, 4, 0],\n        [0, 0, 0, 0, 1, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4],\n        [4, 0, 1, 2, 3],\n        [0, 0, 0, 0, 1, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4],\n        [1, 0, 2, 3, 4],\n        [0, 0, 0, 0, 1, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4],\n        [2, 0, 1, 3, 4],\n        [0, 0, 0, 0, 1, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4],\n        [0, 1, 4, 2, 3],\n        [0, 0, 0, 0, 1, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4],\n        [0, 1, 3, 4, 2],\n        [0, 0, 0, 0, 1, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4],\n        [0, 1, 3, 2, 4],\n        [0, 0, 0, 0, 1, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5, 6],\n        [2, 1, 0, 3, 4, 5, 6],\n        [0, 0, 0, 0, 2, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5, 6],\n        [0, 3, 4, 1, 2, 5, 6],\n        [0, 0, 0, 0, 2, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5, 6],\n        [0, 2, 3, 5, 6, 1, 4],\n        [0, 0, 0, 0, 2, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5, 6],\n        [0, 1, 5, 3, 2, 4, 6],\n        [0, 0, 0, 0, 2, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n        [8, 1, 3, 4, 5, 6, 0, 7, 2, 9],\n        [0, 0, 0, 0, 3, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n        [9, 5, 0, 7, 1, 2, 3, 4, 6, 8],\n        [0, 0, 0, 0, 3, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n\n      [\n        [0, 1],\n        [2, 1, 0],\n        [0, 0, 1, 0, 2, 0, 0],\n        [0, 0, 1, 0, 1, 0, 0],\n      ],\n      [\n        [0, 1],\n        [1, 0, 2],\n        [0, 0, 1, 0, 2, 0, 0],\n        [0, 0, 1, 0, 1, 0, 0],\n      ],\n      [\n        [0, 1, 2],\n        [3, 0, 2, 1],\n        [0, 0, 1, 0, 2, 0, 0],\n        [0, 0, 1, 0, 1, 0, 0],\n      ],\n      [\n        [0, 1, 2],\n        [0, 2, 1, 3],\n        [0, 0, 1, 0, 2, 0, 0],\n        [0, 0, 1, 0, 1, 0, 0],\n      ],\n      [\n        [0, 1, 2],\n        [0, 2, 3, 1],\n        [0, 0, 1, 0, 2, 0, 0],\n        [0, 0, 1, 0, 1, 0, 0],\n      ],\n      [\n        [0, 1, 2],\n        [1, 2, 3, 0],\n        [0, 0, 1, 0, 2, 0, 0],\n        [0, 0, 1, 0, 1, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4],\n        [5, 4, 3, 2, 1, 0],\n        [0, 0, 1, 0, 5, 0, 0],\n        [0, 0, 1, 0, 1, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4],\n        [5, 4, 3, 6, 2, 1, 0],\n        [0, 0, 2, 0, 6, 0, 0],\n        [0, 0, 2, 0, 2, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4],\n        [5, 4, 3, 6, 2, 1, 0, 7],\n        [0, 0, 3, 0, 7, 0, 0],\n        [0, 0, 3, 0, 3, 0, 0],\n      ],\n\n      [\n        [0, 1, 2],\n        [1, 0],\n        [0, 0, 0, 0, 1, 0, 1],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n      [\n        [2, 0, 1],\n        [1, 0],\n        [0, 0, 0, 0, 1, 0, 1],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n      [\n        [7, 0, 1, 8, 2, 3, 4, 5, 9],\n        [7, 5, 4, 8, 3, 2, 1, 0],\n        [0, 0, 0, 0, 5, 0, 1],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n      [\n        [7, 0, 1, 8, 2, 3, 4, 5, 9],\n        [5, 4, 8, 3, 2, 1, 0, 9],\n        [0, 0, 0, 0, 5, 0, 1],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n      [\n        [7, 0, 1, 8, 2, 3, 4, 5, 9],\n        [7, 5, 4, 3, 2, 1, 0, 9],\n        [0, 0, 0, 0, 5, 0, 1],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n      [\n        [7, 0, 1, 8, 2, 3, 4, 5, 9],\n        [5, 4, 3, 2, 1, 0, 9],\n        [0, 0, 0, 0, 5, 0, 2],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n      [\n        [7, 0, 1, 8, 2, 3, 4, 5, 9],\n        [5, 4, 3, 2, 1, 0],\n        [0, 0, 0, 0, 5, 0, 3],\n        [0, 0, 0, 0, 0, 0, 3],\n      ],\n\n      [[0], [1], [0, 0, 1, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0]],\n      [[0], [1, 2], [0, 0, 2, 0, 2, 0, 0], [0, 0, 1, 0, 1, 0, 0]],\n      [[0, 2], [1], [0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 1]],\n      [\n        [0, 2],\n        [1, 2],\n        [0, 0, 1, 0, 1, 0, 1],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 2],\n        [2, 1],\n        [0, 0, 1, 0, 2, 0, 1],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2],\n        [3, 4, 5],\n        [0, 0, 3, 0, 3, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2],\n        [2, 4, 5],\n        [0, 0, 2, 0, 3, 0, 2],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5],\n        [6, 7, 8, 9, 10, 11],\n        [0, 0, 6, 0, 6, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5],\n        [6, 1, 7, 3, 4, 8],\n        [0, 0, 3, 0, 3, 0, 3],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5],\n        [6, 7, 3, 8],\n        [0, 0, 3, 0, 3, 0, 5],\n        [0, 0, 0, 0, 0, 0, 2],\n      ],\n\n      [\n        [0, 1, 2],\n        [3, 2, 1],\n        [0, 0, 1, 0, 2, 0, 1],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2],\n        [2, 1, 3],\n        [0, 0, 1, 0, 3, 0, 1],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [1, 2, 0],\n        [2, 1, 3],\n        [0, 0, 1, 0, 2, 0, 1],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [1, 2, 0],\n        [3, 2, 1],\n        [0, 0, 1, 0, 3, 0, 1],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5],\n        [6, 1, 3, 2, 4, 7],\n        [0, 0, 2, 0, 3, 0, 2],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5],\n        [6, 1, 7, 3, 2, 4],\n        [0, 0, 2, 0, 3, 0, 2],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n      [\n        [0, 1, 2, 3, 4, 5],\n        [6, 7, 3, 2, 4],\n        [0, 0, 2, 0, 3, 0, 3],\n        [0, 0, 0, 0, 0, 0, 1],\n      ],\n      [\n        [0, 2, 3, 4, 5],\n        [6, 1, 7, 3, 2, 4],\n        [0, 0, 3, 0, 4, 0, 2],\n        [0, 0, 1, 0, 1, 0, 0],\n      ],\n\n      [\n        [{ key: 0, children: [0] }],\n        [{ key: 0, children: [] }],\n        [0, 0, 0, 0, 0, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n\n      [\n        [0, 1, { children: [0], key: 2 }],\n        [{ key: 2, children: [] }],\n        [0, 0, 0, 0, 0, 0, 2],\n        [1, 0, 0, 0, 0, 1, 2],\n      ],\n\n      [\n        [{ key: 0, children: [] }],\n        [1, 2, { key: 0, children: [0] }],\n        [0, 0, 3, 0, 3, 0, 0],\n        [1, 0, 3, 0, 3, 1, 0],\n      ],\n\n      [\n        [0, { key: 1, children: [0, 1] }, 2],\n        [3, 2, { key: 1, children: [1, 0] }],\n        [0, 0, 1, 0, 3, 0, 1],\n        [1, 0, 3, 0, 2, 2, 0],\n      ],\n\n      [\n        [0, { key: 1, children: [0, 1] }, 2],\n        [2, { key: 1, children: [1, 0] }, 3],\n        [0, 0, 1, 0, 4, 0, 1],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n\n      [\n        [{ key: 1, children: [0, 1] }, { key: 2, children: [0, 1] }, 0],\n        [{ key: 2, children: [1, 0] }, { key: 1, children: [1, 0] }, 3],\n        [0, 0, 1, 0, 4, 0, 1],\n        [0, 0, 0, 0, 0, 0, 0],\n      ],\n\n      [\n        [{ key: 1, children: [0, 1] }, { key: 2, children: [] }, 0],\n        [3, { key: 2, children: [1, 0] }, { key: 1, children: [] }],\n        [0, 0, 3, 0, 5, 0, 1],\n        [1, 0, 3, 0, 2, 2, 0],\n      ],\n\n      [\n        [0, { key: 1, children: [] }, 2, { key: 3, children: [1, 0] }, 4, 5],\n        [6, { key: 1, children: [0, 1] }, { key: 3, children: [] }, 2, 4, 7],\n        [0, 0, 4, 0, 5, 0, 2],\n        [1, 0, 3, 0, 2, 2, 0],\n      ],\n\n      [\n        [\n          0,\n          { key: 1, children: [] },\n          { key: 2, children: [] },\n          { key: 3, children: [] },\n          { key: 4, children: [] },\n          5,\n        ],\n        [\n          { key: 6, children: [{ key: 1, children: [1] }] },\n          7,\n          { key: 3, children: [1] },\n          { key: 2, children: [1] },\n          { key: 4, children: [1] },\n        ],\n        [2, 0, 5, 0, 8, 0, 3],\n        [2, 0, 5, 0, 5, 2, 1],\n      ],\n\n      [\n        [0, 1, { key: 2, children: [0] }, 3, { key: 4, children: [0] }, 5],\n        [6, 7, 3, { key: 2, children: [] }, { key: 4, children: [] }],\n        [0, 0, 2, 0, 3, 0, 3],\n        [1, 0, 1, 0, 0, 2, 1],\n      ],\n    ];\n\n    describe('syncChildren string children', () => {\n      it(\"null => 'abc'\", () => {\n        const f = document.createDocumentFragment();\n        const a = createElement('div', null);\n        const b = createElement('div', null, 'abc');\n        render(a, f);\n        render(b, f);\n        expect(f.firstChild.childNodes.length).toBe(1);\n        expect(f.firstChild.firstChild.nodeValue).toBe('abc');\n      });\n\n      it(\"'abc' => null\", () => {\n        const f = document.createDocumentFragment();\n        const a = createElement('div', null, 'abc');\n        const b = createElement('div', null);\n        render(a, f);\n        render(b, f);\n        expect(f.firstChild.childNodes.length).toBe(0);\n      });\n\n      it(\"'abc' => 'cde'\", () => {\n        const f = document.createDocumentFragment();\n        const a = createElement('div', null, 'abc');\n        const b = createElement('div', null, 'cde');\n        render(a, f);\n        render(b, f);\n        expect(f.firstChild.childNodes.length).toBe(1);\n        expect(f.firstChild.firstChild.nodeValue).toBe('cde');\n      });\n\n      it(\"[ div ] => 'cde'\", () => {\n        const f = document.createDocumentFragment();\n        const a = createElement('div', null, createElement('div', null));\n        const b = createElement('div', null, 'cde');\n        render(a, f);\n        render(b, f);\n        expect(f.firstChild.childNodes.length).toBe(1);\n        expect(f.firstChild.firstChild.nodeValue).toBe('cde');\n      });\n\n      it(\"'cde' => [ div ]\", () => {\n        const f = document.createDocumentFragment();\n        const a = createElement('div', null, 'cde');\n        const b = createElement('div', null, createElement('div', null));\n        render(a, f);\n        render(b, f);\n        expect(f.firstChild.childNodes.length).toBe(1);\n        expect(f.firstChild.firstChild.tagName).toBe('DIV');\n      });\n\n      function gen(item, keys) {\n        if (typeof item === 'number') {\n          return keys\n            ? createVNode(\n                VNodeFlags.HtmlElement,\n                'div',\n                null,\n                createTextVNode(item),\n                ChildFlags.HasVNodeChildren,\n                null,\n                item,\n              )\n            : createVNode(\n                VNodeFlags.HtmlElement,\n                'div',\n                null,\n                createTextVNode(item),\n                ChildFlags.HasVNodeChildren,\n              );\n        } else if (Array.isArray(item)) {\n          const result = [];\n          for (let i = 0; i < item.length; i++) {\n            result.push(gen(item[i], keys));\n          }\n          return result;\n        } else {\n          if (keys) {\n            return createElement(\n              'div',\n              { key: item.key },\n              gen(item.children, keys),\n            );\n          } else {\n            return createElement('div', null, gen(item.children, keys));\n          }\n        }\n      }\n\n      function checkInnerHtmlEquals(ax, bx, cx, keys) {\n        let a, b, c;\n\n        if (keys) {\n          a = createElement('div', { key: ax }, ax);\n          b = createElement('div', { key: bx }, bx);\n          c = createElement('div', { key: cx }, cx);\n        } else {\n          a = createElement('div', null, ax);\n          b = createElement('div', null, bx);\n          c = createElement('div', null, cx);\n        }\n\n        const aDiv = document.createElement('div');\n        const bDiv = document.createElement('div');\n        render(a, aDiv);\n        render(b, bDiv);\n\n        render(c, aDiv);\n\n        expect(aDiv.innerHTML).toBe(bDiv.innerHTML);\n      }\n\n      describe('Keyed algorithm', () => {\n        for (const t of TESTS) {\n          const name = JSON.stringify(t[0]) + ' => ' + JSON.stringify(t[1]);\n\n          it(name, () => {\n            checkInnerHtmlEquals(\n              gen(t[0], true),\n              gen(t[1], true),\n              gen(t[1], true),\n              true,\n            );\n          });\n        }\n      });\n\n      describe('Non keyed algorithm', () => {\n        for (const t of TESTS) {\n          const name = JSON.stringify(t[0]) + ' => ' + JSON.stringify(t[1]);\n\n          it(name, () => {\n            checkInnerHtmlEquals(\n              gen(t[0], false),\n              gen(t[1], false),\n              gen(t[1], false),\n              false,\n            );\n          });\n        }\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/patchMixedKeyed.spec.js",
    "content": "import { render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\nfunction spanTagWithText(text) {\n  return createElement(\n    'span',\n    {\n      className: 'TableCell',\n    },\n    text,\n  );\n}\n\nfunction spanTagWithKeyAndText(key, text) {\n  return createElement(\n    'span',\n    {\n      className: 'TableCell',\n      key,\n    },\n    text,\n  );\n}\n\nconst template = function (child) {\n  return createElement('div', null, child);\n};\n\ndescribe('Mixed of Keyed/Non-Keyed nodes', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  // TOOD: Is mixin keyed non keyed supported this way?\n  it('should remove two keyed nodes, and move a non-key child node', () => {\n    render(\n      template([spanTagWithKeyAndText('d', 'b'), spanTagWithText('c')]),\n      container,\n    );\n    expect(container.textContent).toBe('bc');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n        spanTagWithText('c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abcc');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([spanTagWithKeyAndText('d', 'b'), spanTagWithText('c')]),\n      container,\n    );\n    expect(container.textContent).toBe('bc');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n        spanTagWithText('c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abcc');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        null,\n        spanTagWithKeyAndText('b', 'b'),\n        undefined,\n        spanTagWithKeyAndText('e', 'c'),\n        spanTagWithText('c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abcc');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        null,\n        spanTagWithKeyAndText('b', 'b'),\n        undefined,\n        spanTagWithKeyAndText('e', 'c'),\n        spanTagWithText('c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abcc');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([spanTagWithKeyAndText('d', 'b'), spanTagWithText('c')]),\n      container,\n    );\n    expect(container.textContent).toBe('bc');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n\n  it('should swap the last child and add three non-key children', () => {\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('ab');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c'),\n        spanTagWithKeyAndText('e', 'a'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bcac');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('ab');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n\n  it('should swap, and a keyed child at the end, and add one non-key child', () => {\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithKeyAndText('e', 'a'),\n        spanTagWithKeyAndText('f', 'c'),\n        spanTagWithText('c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bacc');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        null,\n        spanTagWithKeyAndText('b', 'b'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('ab');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithKeyAndText('e', 'a'),\n        spanTagWithKeyAndText('f', 'c'),\n        spanTagWithText('c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bacc');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        undefined,\n        spanTagWithKeyAndText('e', 'a'),\n        spanTagWithKeyAndText('f', 'c'),\n        spanTagWithText('c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bacc');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('ab');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n\n  it('should insert keyed nodes where the last key is a non-keyed node', () => {\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('f', 'b'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('ab');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'c'),\n        spanTagWithKeyAndText('e', 'c'),\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithKeyAndText('e2', 'b'),\n        spanTagWithText('g'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('ccbbg');\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('f', 'b'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('ab');\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('f', 'b'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('ab');\n  });\n\n  it('should remove the first keyed node child, and add two non-key child nodes', () => {\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(\n      template([\n        spanTagWithKeyAndText('a', 'a'),\n        spanTagWithKeyAndText('b', 'b'),\n        spanTagWithKeyAndText('e', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(\n      template([\n        spanTagWithKeyAndText('d', 'b'),\n        spanTagWithText('c1'),\n        spanTagWithText('c2'),\n        spanTagWithKeyAndText('f', 'c'),\n      ]),\n      container,\n    );\n    expect(container.textContent).toBe('bc1c2c');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/patchNonKeyedChildren.spec.js",
    "content": "import { render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\nfunction generateNodes(array) {\n  let i, id;\n  const children = [];\n\n  for (i = 0; i < array.length; i++) {\n    id = array[i];\n\n    children.push(createElement('div', { key: String(id) }, id));\n  }\n  return children;\n}\n\nfunction spanTagWithText(text) {\n  return createElement(\n    'span',\n    {\n      className: 'TableCell',\n    },\n    text,\n  );\n}\n\ndescribe('Non Keyed nodes', () => {\n  let container;\n\n  const template = function (child) {\n    return createElement('div', null, child);\n  };\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should add all nodes', () => {\n    render(template(generateNodes([])), container);\n    render(template(generateNodes(['#0', '#1', '#2', '#3'])), container);\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should remove two keys at the beginning', () => {\n    render(template(generateNodes(['a', 'b', 'c'])), container);\n    render(template(generateNodes(['c'])), container);\n    expect(container.textContent).toBe('c');\n    expect(container.firstChild.childNodes.length).toBe(1);\n  });\n  it('should size up', () => {\n    render(template(generateNodes(['#0', '#1'])), container);\n    render(template(generateNodes(['#0', '#1', '#2', '#3'])), container);\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should size down', () => {\n    render(template(generateNodes(['#0', '#1', '#2', '#3'])), container);\n    render(template(generateNodes(['#0', '#1'])), container);\n    expect(container.textContent).toBe('#0#1');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should clear all nodes', () => {\n    render(template(generateNodes(['#0', '#1', '#2', '#3'])), container);\n    render(template(generateNodes([])), container);\n    expect(container.textContent).toBe('');\n    expect(container.firstChild.childNodes.length).toBe(0);\n  });\n  it('should work with mixed nodes', () => {\n    render(template(generateNodes(['1', '#0', '#1', '#2'])), container);\n    render(template(generateNodes(['#0', '#1', '#2', '#3'])), container);\n    expect(container.textContent).toBe('#0#1#2#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key for start to end', () => {\n    render(template(generateNodes(['a', '#0', '#1', '#2'])), container);\n    render(template(generateNodes(['#0', '#1', '#2', 'a'])), container);\n    expect(container.textContent).toBe('#0#1#2a');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key', () => {\n    render(template(generateNodes(['#0', 'a', '#2', '#3'])), container);\n    render(template(generateNodes(['#0', '#1', 'a', '#3'])), container);\n    expect(container.textContent).toBe('#0#1a#3');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a key with a size up', () => {\n    render(template(generateNodes(['a', '#1', '#2', '#3'])), container);\n    render(\n      template(generateNodes(['#0', '#1', '#2', '#3', 'a', '#5'])),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3a#5');\n    expect(container.firstChild.childNodes.length).toBe(6);\n    render(template(generateNodes(['a', '#1', '#2', '#3'])), container);\n    render(\n      template(generateNodes(['#0', '#1', '#2', '#3', 'a', '#5'])),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3a#5');\n    expect(container.firstChild.childNodes.length).toBe(6);\n    render(template(generateNodes(['a', '#1', '#2', '#3'])), container);\n    render(\n      template(generateNodes(['#0', '#1', '#2', '#3', 'a', '#5'])),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3a#5');\n    expect(container.firstChild.childNodes.length).toBe(6);\n    render(template(generateNodes(['a', '#1', '#2', '#3'])), container);\n    render(\n      template(generateNodes(['#0', '#1', '#2', '#3', 'a', '#5'])),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3a#5');\n    expect(container.firstChild.childNodes.length).toBe(6);\n    render(template(generateNodes(['a', '#1', '#2', '#4'])), container);\n    render(\n      template(generateNodes(['#0', '#1', '#2', '#4', 'a', '#5'])),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#4a#5');\n    expect(container.firstChild.childNodes.length).toBe(6);\n    render(template(generateNodes(['a', '#1', '#2', '#3'])), container);\n    render(\n      template(generateNodes(['#0', '#1', '#2', '#3', 'a', '#5'])),\n      container,\n    );\n    expect(container.textContent).toBe('#0#1#2#3a#5');\n    expect(container.firstChild.childNodes.length).toBe(6);\n  });\n\n  it('should move a key with a size down', () => {\n    render(template(generateNodes(['a', '#1', '#2', '#3'])), container);\n    render(template(generateNodes(['#0', 'a', '#2'])), container);\n    expect(container.textContent).toBe('#0a#2');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should avoid unnecessary reordering', () => {\n    render(template(generateNodes(['#0', 'a', '#2'])), container);\n    render(template(generateNodes(['#0', 'a', '#2'])), container);\n    expect(container.textContent).toBe('#0a#2');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should work with keyed nodes', () => {\n    render(template(generateNodes([0, 1, 2, 3, 4])), container);\n    render(template(generateNodes([1, 2, 3, 4, 0])), container);\n    expect(container.textContent).toBe('12340');\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateNodes([0, 1, 2, 3, 4])), container);\n    render(template(generateNodes([1, 7, 3, 4, 5])), container); // this originally had duplicate keys!\n    expect(container.textContent).toBe('17345');\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateNodes([1, 2, 3, 4, 0])), container);\n    expect(container.textContent).toBe('12340');\n  });\n\n  it('should reorder keys', () => {\n    render(\n      template(generateNodes(['1', '2', '3', '4', 'abc', '6', 'def', '7'])),\n      container,\n    );\n    render(\n      template(generateNodes(['7', '4', '3', '2', '6', 'abc', 'def', '1'])),\n      container,\n    );\n    expect(container.textContent).toBe('74326abcdef1');\n    expect(container.firstChild.childNodes.length).toBe(8);\n  });\n  it('should remove one key at the start', () => {\n    render(template(generateNodes(['a', 'b', 'c'])), container);\n    render(template(generateNodes(['b', 'c'])), container);\n    expect(container.textContent).toBe('bc');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    render(template(generateNodes(['a', 'b', 'c'])), container);\n    render(template(generateNodes(['b', 'c'])), container);\n    expect(container.textContent).toBe('bc');\n    expect(container.firstChild.childNodes.length).toBe(2);\n    render(template(generateNodes(['a', 'b', 'c', 'd'])), container);\n    render(template(generateNodes(['d', 'c', 'b', 'a'])), container);\n    expect(container.textContent).toBe('dcba');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  it('should do a complex reverse', () => {\n    render(template(generateNodes(['a', 'b', 'c', 'd'])), container);\n    render(template(generateNodes(['d', 'c', 'b', 'a'])), container);\n    expect(container.textContent).toBe('dcba');\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateNodes(['a', 'b', 'c'])), container);\n    render(template(generateNodes([0])), container);\n    expect(container.textContent).toBe('0');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    render(template(generateNodes(['a', 'b', 'c', 'd'])), container);\n    render(template(generateNodes(['d', 'c', 'b', 'a'])), container);\n    expect(container.textContent).toBe('dcba');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n\n  it('should remove two keys at the start', () => {\n    render(template(generateNodes(['a', 'b', 'c'])), container);\n    render(template(generateNodes(['c'])), container);\n    expect(container.textContent).toBe('c');\n    expect(container.firstChild.childNodes.length).toBe(1);\n  });\n  it('should add one key to start', () => {\n    render(template(generateNodes(['a', 'b'])), container);\n    render(template(generateNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should add two key to start', () => {\n    render(template(generateNodes(['c'])), container);\n    render(template(generateNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should remove one key at the end', () => {\n    render(template(generateNodes(['a', 'b', 'c'])), container);\n    render(template(generateNodes(['a', 'b'])), container);\n    expect(container.textContent).toBe('ab');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should remove two keys at the end', () => {\n    render(template(generateNodes(['a', 'b', 'c'])), container);\n    render(template(generateNodes(['a'])), container);\n    expect(container.textContent).toBe('a');\n    expect(container.firstChild.childNodes.length).toBe(1);\n  });\n  it('should add one key at the end', () => {\n    render(template(generateNodes(['a', 'b'])), container);\n    render(template(generateNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should add two key at the end', () => {\n    render(template(generateNodes(['a'])), container);\n    render(template(generateNodes(['a', 'b', 'c'])), container);\n    expect(container.textContent).toBe('abc');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should add to end, delete from center & reverse', () => {\n    render(template(generateNodes(['a', 'b', 'c', 'd'])), container);\n    render(template(generateNodes(['e', 'd', 'c', 'a'])), container);\n    expect(container.textContent).toBe('edca');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should add to the beginning and remove', () => {\n    render(template(generateNodes(['c', 'd'])), container);\n    render(template(generateNodes(['a', 'b', 'c', 'e'])), container);\n    expect(container.textContent).toBe('abce');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should keep a central pivot', () => {\n    render(template(generateNodes(['1', '2', '3'])), container);\n    render(template(generateNodes(['4', '2', '5'])), container);\n    expect(container.textContent).toBe('425');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should insert to the middle', () => {\n    render(template(generateNodes(['c', 'd', 'e'])), container);\n    render(template(generateNodes(['a', 'b', 'e'])), container);\n    expect(container.textContent).toBe('abe');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should shuffle, insert and remove', () => {\n    render(\n      template(generateNodes(['a', 'b', 'c', 'd', 'e', 'f', 'g'])),\n      container,\n    );\n    render(template(generateNodes(['b', 'c', 'a'])), container);\n    expect(container.textContent).toBe('bca');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should remove a element from the middle', () => {\n    render(template(generateNodes([1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateNodes([1, 2, 4, 5])), container);\n    expect(container.textContent).toBe('1245');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a element forward', () => {\n    render(template(generateNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateNodes([2, 3, 1, 4])), container);\n    expect(container.textContent).toBe('2314');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move a element to the end', () => {\n    render(template(generateNodes([1, 2, 3])), container);\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateNodes([2, 3, 1])), container);\n    expect(container.textContent).toBe('231');\n    expect(container.firstChild.childNodes.length).toBe(3);\n  });\n  it('should move a element backwards', () => {\n    render(template(generateNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateNodes([1, 4, 2, 3])), container);\n    expect(container.textContent).toBe('1423');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should swap first and last', () => {\n    render(template(generateNodes([1, 2, 3, 4])), container);\n    expect(container.firstChild.childNodes.length).toBe(4);\n    render(template(generateNodes([4, 2, 3, 1])), container);\n    expect(container.textContent).toBe('4231');\n    expect(container.firstChild.childNodes.length).toBe(4);\n  });\n  it('should move to left and replace', () => {\n    render(template(generateNodes([1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(5);\n    render(template(generateNodes([4, 1, 2, 3, 6])), container);\n    expect(container.textContent).toBe('41236');\n    expect(container.firstChild.childNodes.length).toBe(5);\n  });\n  it('should move to left and leave a hole', () => {\n    render(template(generateNodes([1, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(3);\n    render(template(generateNodes([4, 6])), container);\n    expect(container.textContent).toBe('46');\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n  it('should do something', () => {\n    render(template(generateNodes([0, 1, 2, 3, 4, 5])), container);\n    expect(container.firstChild.childNodes.length).toBe(6);\n    render(template(generateNodes([4, 3, 2, 1, 5, 0])), container);\n    expect(container.textContent).toBe('432150');\n    expect(container.firstChild.childNodes.length).toBe(6);\n  });\n\n  describe('Without blueprints', () => {\n    it('should swap two non-keyed children', () => {\n      render(\n        template([spanTagWithText('a'), [], spanTagWithText('b')]),\n        container,\n      );\n      expect(container.textContent).toBe('ab');\n      render(\n        template([spanTagWithText('b'), null, spanTagWithText('a')]),\n        container,\n      );\n      expect(container.textContent).toBe('ba');\n    });\n\n    it('should do a complex move of non-keyed to the beginning', () => {\n      render(\n        template([\n          spanTagWithText('x'),\n          spanTagWithText('y'),\n          spanTagWithText('a'),\n          spanTagWithText('b'),\n          spanTagWithText('d'),\n          spanTagWithText('c'),\n          spanTagWithText('v'),\n          spanTagWithText('w'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('xyabdcvw');\n      expect(container.firstChild.childNodes.length).toBe(8);\n      render(\n        template([\n          spanTagWithText('y'),\n          spanTagWithText('x'),\n          spanTagWithText('a'),\n          spanTagWithText('d2'),\n          spanTagWithText('f'),\n          spanTagWithText('g'),\n          spanTagWithText('w'),\n          spanTagWithText('v'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('yxad2fgwv');\n      expect(container.firstChild.childNodes.length).toBe(8);\n      render(\n        template([\n          spanTagWithText('x'),\n          spanTagWithText('y'),\n          spanTagWithText('a'),\n          spanTagWithText('b'),\n          spanTagWithText('d'),\n          spanTagWithText('c'),\n          spanTagWithText('v'),\n          spanTagWithText('w'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('xyabdcvw');\n      expect(container.firstChild.childNodes.length).toBe(8);\n      render(\n        template([\n          spanTagWithText('y'),\n          spanTagWithText('x'),\n          undefined,\n          spanTagWithText('a'),\n          spanTagWithText('d2'),\n          spanTagWithText('f'),\n          spanTagWithText('g'),\n          spanTagWithText('w'),\n          spanTagWithText('v'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('yxad2fgwv');\n      expect(container.firstChild.childNodes.length).toBe(8);\n    });\n\n    it('should do a advanced shuffle', () => {\n      render(\n        template([\n          spanTagWithText('a'),\n          spanTagWithText('b'),\n          spanTagWithText('c'),\n          spanTagWithText('d'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('abcd');\n      expect(container.firstChild.childNodes.length).toBe(4);\n      render(\n        template([\n          spanTagWithText('e'),\n          spanTagWithText('b'),\n          spanTagWithText('f'),\n          spanTagWithText('g'),\n          spanTagWithText('c'),\n          spanTagWithText('a'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('ebfgca');\n      expect(container.firstChild.childNodes.length).toBe(6);\n      render(\n        template([\n          spanTagWithText('a'),\n          spanTagWithText('6'),\n          null,\n          spanTagWithText('c'),\n          spanTagWithText('d'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('a6cd');\n      expect(container.firstChild.childNodes.length).toBe(4);\n      render(\n        template([\n          spanTagWithText('e'),\n          spanTagWithText('b'),\n          spanTagWithText('f'),\n          spanTagWithText('g'),\n          spanTagWithText('c'),\n          spanTagWithText('a'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('ebfgca');\n      expect(container.firstChild.childNodes.length).toBe(6);\n      render(\n        template([\n          spanTagWithText('a'),\n          spanTagWithText('b'),\n          undefined,\n          spanTagWithText('c'),\n          spanTagWithText('d'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('abcd');\n      expect(container.firstChild.childNodes.length).toBe(4);\n      render(\n        template([\n          spanTagWithText('e'),\n          spanTagWithText('b'),\n          spanTagWithText('f'),\n          spanTagWithText('g'),\n          spanTagWithText('c'),\n          spanTagWithText('a'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('ebfgca');\n      expect(container.firstChild.childNodes.length).toBe(6);\n    });\n\n    it('should do a complex reverse #2', () => {\n      render(\n        template([\n          spanTagWithText('#0'),\n          spanTagWithText('#1'),\n          spanTagWithText('#2'),\n        ]),\n        container,\n      );\n      render(\n        template([\n          spanTagWithText('#2'),\n          spanTagWithText('#1'),\n          spanTagWithText('#0'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('#2#1#0');\n      expect(container.firstChild.childNodes.length).toBe(3);\n      render(\n        template([\n          spanTagWithText('#2'),\n          spanTagWithText('#1'),\n          spanTagWithText('#0'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('#2#1#0');\n      expect(container.firstChild.childNodes.length).toBe(3);\n      render(\n        template([\n          spanTagWithText('#2'),\n          spanTagWithText('#1'),\n          null,\n          null,\n          null,\n          spanTagWithText('#0'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('#2#1#0');\n      expect(container.firstChild.childNodes.length).toBe(3);\n      render(\n        template([\n          spanTagWithText('#2'),\n          spanTagWithText('#1'),\n          spanTagWithText('#4'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('#2#1#4');\n      expect(container.firstChild.childNodes.length).toBe(3);\n    });\n\n    it('should add to end, delete from center & reverse #2', () => {\n      render(\n        template([\n          spanTagWithText('a'),\n          spanTagWithText('b'),\n          spanTagWithText('c'),\n          spanTagWithText('d'),\n        ]),\n        container,\n      );\n      render(\n        template([\n          spanTagWithText('e'),\n          spanTagWithText('d'),\n          spanTagWithText('c'),\n          spanTagWithText('a'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('edca');\n      expect(container.firstChild.childNodes.length).toBe(4);\n      render(\n        template([\n          spanTagWithText('#2'),\n          spanTagWithText('#1'),\n          spanTagWithText('#0'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('#2#1#0');\n      expect(container.firstChild.childNodes.length).toBe(3);\n      render(\n        template([\n          spanTagWithText('#2'),\n          spanTagWithText('#1'),\n          spanTagWithText('#4'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('#2#1#4');\n      expect(container.firstChild.childNodes.length).toBe(3);\n      render(\n        template([\n          spanTagWithText('a'),\n          spanTagWithText('b'),\n          spanTagWithText('c'),\n          spanTagWithText('d'),\n        ]),\n        container,\n      );\n      render(\n        template([\n          spanTagWithText('e'),\n          spanTagWithText('d'),\n          spanTagWithText('c'),\n          spanTagWithText('a'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('edca');\n      expect(container.firstChild.childNodes.length).toBe(4);\n    });\n\n    it('should insert to the middle #2', () => {\n      render(\n        template([\n          spanTagWithText('c'),\n          spanTagWithText('d'),\n          spanTagWithText('e'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('cde');\n      expect(container.firstChild.childNodes.length).toBe(3);\n      render(\n        template([\n          spanTagWithText('a'),\n          spanTagWithText('b'),\n          spanTagWithText('e'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('abe');\n      expect(container.firstChild.childNodes.length).toBe(3);\n      render(\n        template([\n          spanTagWithText('c'),\n          spanTagWithText('d'),\n          null,\n          null,\n          null,\n          spanTagWithText('e'),\n        ]),\n        container,\n      );\n      expect(container.textContent).toBe('cde');\n      expect(container.firstChild.childNodes.length).toBe(3);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/patching.spec.js",
    "content": "import { Component, createFragment, render, rerender } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('patching keyed lists (non-jsx)', () => {\n  function createDataModels() {\n    const dataModels = [];\n\n    dataModels.push(addGroupSingleChild(500));\n    dataModels.push(addGroupSingleChild(400));\n    dataModels.push(addGroupSingleChild(5));\n    dataModels.push(addGroupSingleChild(50));\n    dataModels.push(addGroupSingleChild(300));\n    dataModels.push(addGroupSingleChild(0));\n\n    return dataModels;\n  }\n\n  function addGroupSingleChild(count) {\n    const dataModel = [];\n    for (let i = 0; i < count; i++) {\n      dataModel.push({\n        key: i,\n        children: null,\n      });\n    }\n    return dataModel;\n  }\n\n  function shuffle(dataModel) {\n    for (let e, t, n = dataModel.length; n !== 0; ) {\n      e = Math.floor(Math.random() * n--);\n      t = dataModel[n];\n      dataModel[n] = dataModel[e];\n      dataModel[e] = t;\n    }\n  }\n\n  function createExpectedChildren(nodes) {\n    const children = [];\n    let i, e, n;\n\n    for (i = 0; i < nodes.length; i++) {\n      n = nodes[i];\n      if (n.children !== null) {\n        e = document.createElement('div');\n        render(n.children, e);\n        // This code is here to make typescript happy... lol\n        for (let a = 0; a < e.children.length; a++) {\n          children.push(e.children[a]);\n        }\n        // We could just return e.children, but that conflicts with typescript types...\n        return children;\n      } else {\n        e = document.createElement('span');\n        e.textContent = n.key.toString();\n        children.push(e);\n      }\n    }\n\n    return children;\n  }\n\n  function createExpected(nodes) {\n    const c = document.createElement('div');\n    const e = document.createElement('div');\n    const children = createExpectedChildren(nodes);\n    for (let i = 0; i < children.length; i++) {\n      e.appendChild(children[i]);\n    }\n    c.appendChild(e);\n    return c.innerHTML;\n  }\n\n  const container = document.createElement('div');\n  let dataModels = null;\n\n  beforeEach(function () {\n    dataModels = createDataModels();\n  });\n\n  afterEach(function () {\n    dataModels = null;\n  });\n\n  function renderTree(nodes) {\n    const children = new Array(nodes.length);\n    let i;\n    let n;\n\n    for (i = 0; i < nodes.length; i++) {\n      n = nodes[i];\n      if (n.children !== null) {\n        children[i] = createElement(\n          'div',\n          { key: n.key },\n          renderTree(n.children),\n        );\n      } else {\n        children[i] = createElement('span', { key: n.key }, n.key);\n      }\n    }\n    return children;\n  }\n\n  function renderModel(dataModel) {\n    render(createElement('div', null, renderTree(dataModel)), container);\n  }\n\n  it('should render various combinations', () => {\n    let dataModel = dataModels[0];\n\n    renderModel(dataModel);\n\n    expect(container.innerHTML).toBe(createExpected(dataModel));\n\n    dataModel = dataModels[0];\n\n    renderModel(dataModel);\n\n    expect(container.innerHTML).toBe(createExpected(dataModel));\n\n    dataModel = dataModels[3];\n    dataModel.reverse();\n\n    renderModel(dataModel);\n\n    expect(container.innerHTML).toBe(createExpected(dataModel));\n\n    render(null, container);\n\n    dataModel = dataModels[0];\n    dataModel.reverse();\n    render(null, container);\n\n    dataModel = dataModels[0];\n    dataModel.reverse();\n\n    renderModel(dataModel);\n\n    expect(container.innerHTML).toBe(createExpected(dataModel));\n\n    render(null, container);\n\n    dataModel = dataModels[1];\n    dataModel.reverse();\n\n    renderModel(dataModel);\n\n    expect(container.innerHTML).toBe(createExpected(dataModel));\n\n    render(null, container);\n\n    dataModel = dataModels[3];\n\n    renderModel(dataModel);\n\n    expect(container.innerHTML).toBe(createExpected(dataModel));\n\n    render(null, container);\n\n    dataModel = dataModels[1];\n\n    renderModel(dataModel);\n\n    expect(container.innerHTML).toBe(createExpected(dataModel));\n\n    render(null, container);\n\n    dataModel = dataModels[4];\n\n    renderModel(dataModel);\n\n    expect(container.innerHTML).toBe(createExpected(dataModel));\n\n    render(null, container);\n\n    dataModel = dataModels[2];\n    dataModel.reverse();\n\n    renderModel(dataModel);\n\n    expect(container.innerHTML).toBe(createExpected(dataModel));\n\n    render(null, container);\n\n    dataModel = dataModels[3];\n    dataModel.reverse();\n\n    renderModel(dataModel);\n\n    expect(container.innerHTML).toBe(createExpected(dataModel));\n\n    render(null, container);\n\n    dataModel = dataModels[1];\n    shuffle(dataModel);\n\n    renderModel(dataModel);\n\n    expect(container.innerHTML).toBe(createExpected(dataModel));\n\n    render(null, container);\n  });\n\n  it('Portal content should stay within its own portal - Github #1421', () => {\n    const f = (...xs) => createFragment(xs, 0);\n\n    class App extends Component {\n      constructor() {\n        super();\n        this.state = { ids: [] };\n      }\n\n      componentDidMount() {\n        expect(container.outerHTML).toEqual(\n          '<div><h1>App</h1><p>Not found</p><button>Create</button><footer>2018</footer></div>',\n        );\n\n        this.setState({ ids: ['test'] });\n        rerender();\n        expect(container.outerHTML).toEqual(\n          '<div><h1>App</h1><h2>test</h2><footer>2018</footer></div>',\n        );\n\n        this.setState({ ids: [] });\n        rerender();\n        expect(container.outerHTML).toEqual(\n          '<div><h1>App</h1><p>Not found</p><button>Create</button><footer>2018</footer></div>',\n        ); // Fails too, when skipping the previous assertion.\n      }\n\n      render() {\n        const { ids } = this.state;\n        return f(\n          createElement('h1', null, 'App'),\n          f(\n            ids.length\n              ? ids.map((id) => createElement('h2', null, id))\n              : createElement('p', null, 'Not found'),\n            !ids.length && createElement('button', null, 'Create'), // Same condition for simple example.\n          ),\n          createElement('footer', null, '2018'),\n        );\n      }\n    }\n\n    render(createElement(App), container);\n  });\n\n  it('Portal content should stay within its own portal - Github #1421 - variation 2', () => {\n    const f = (...xs) => createFragment(xs, 0);\n\n    class App extends Component {\n      constructor() {\n        super();\n        this.state = { ids: [] };\n      }\n\n      componentDidMount() {\n        expect(container.outerHTML).toEqual(\n          '<div><h1>App</h1><p>Not found</p><button>Create</button><footer>2018</footer></div>',\n        );\n\n        this.setState({ ids: ['test', 'test2'] });\n        rerender();\n        expect(container.outerHTML).toEqual(\n          '<div><h1>App</h1><h2>test</h2><h2>test2</h2><footer>2018</footer></div>',\n        );\n\n        this.setState({ ids: [] });\n        rerender();\n        expect(container.outerHTML).toEqual(\n          '<div><h1>App</h1><p>Not found</p><button>Create</button><footer>2018</footer></div>',\n        ); // Fails too, when skipping the previous assertion.\n      }\n\n      render() {\n        const { ids } = this.state;\n        return f(\n          createElement('h1', null, 'App'),\n          f(\n            ids.length\n              ? ids.map((id) => createElement('h2', null, id))\n              : createElement('p', null, 'Not found'),\n            !ids.length && createElement('button', null, 'Create'), // Same condition for simple example.\n          ),\n          createElement('footer', null, '2018'),\n        );\n      }\n    }\n\n    render(createElement(App), container);\n  });\n\n  it('Portal content should stay within its own portal - Github #1421 - variation 3', () => {\n    const f = (...xs) => createFragment(xs, 0);\n\n    class App extends Component {\n      constructor() {\n        super();\n        this.state = { ids: [] };\n      }\n\n      componentDidMount() {\n        expect(container.outerHTML).toEqual(\n          '<div><h1>App</h1><p>Not found</p><button>Create</button><footer>2018</footer></div>',\n        );\n\n        this.setState({ ids: ['test', 'test2', 'test3'] });\n        rerender();\n        expect(container.outerHTML).toEqual(\n          '<div><h1>App</h1><h2>test</h2><h2>test2</h2><h2>test3</h2><footer>2018</footer></div>',\n        );\n\n        this.setState({ ids: [] });\n        rerender();\n        expect(container.outerHTML).toEqual(\n          '<div><h1>App</h1><p>Not found</p><button>Create</button><footer>2018</footer></div>',\n        ); // Fails too, when skipping the previous assertion.\n      }\n\n      render() {\n        const { ids } = this.state;\n        return f(\n          createElement('h1', null, 'App'),\n          f(\n            ids.length\n              ? ids.map((id) => createElement('h2', null, id))\n              : createElement('p', null, 'Not found'),\n            !ids.length && createElement('button', null, 'Create'), // Same condition for simple example.\n          ),\n          createElement('footer', null, '2018'),\n        );\n      }\n    }\n\n    render(createElement(App), container);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/select.spec.js",
    "content": "import { render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('Select / select multiple (non-JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('should render \"select\" boolean on select options with numbers', () => {\n    const template = (val) =>\n      createElement(\n        'select',\n        {\n          multiple: true,\n          value: val,\n        },\n        createElement(\n          'option',\n          {\n            value: 1,\n          },\n          1,\n        ),\n        createElement(\n          'option',\n          {\n            value: 2,\n          },\n          2,\n        ),\n      );\n\n    render(template(null), container);\n    render(template(), container);\n    render(template(2), container);\n\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"1\">1</option><option value=\"2\">2</option></select>',\n    );\n\n    render(template(1), container);\n\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"1\">1</option><option value=\"2\">2</option></select>',\n    );\n\n    render(template('foo'), container);\n\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"1\">1</option><option value=\"2\">2</option></select>',\n    );\n  });\n\n  // it('should render \"select\" boolean on select options #1 browser', () => {\n  //\n  // \tconst template = (val) => createElement('select', {\n  // \t\tmultiple: true,\n  // \t\tvalue: val\n  // \t}, createElement('option', {\n  // \t\tvalue: 'foo'\n  // \t}, 'foo'), createElement('option', {\n  // \t\tvalue: 'bar'\n  // \t}, 'bar'));\n  //\n  // \trender(template({}), container);\n  // \trender(template(null), container);\n  // \trender(template(undefined), container);\n  // \trender(template('foo'), container);\n  // \texpect(container.firstChild.children[ 0 ].selected).to.eql(true);\n  // \texpect(container.firstChild.children[ 1 ].selected).to.eql(false);\n  // \texpect(\n  // \t\tcontainer.innerHTML\n  // \t).toEqual(\n  // \t\t('<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>')\n  // \t);\n  // \trender(template(undefined), container);\n  // \trender(template(null), container);\n  // \texpect(container.firstChild.children[ 0 ].selected).to.eql(false);\n  // \texpect(container.firstChild.children[ 1 ].selected).to.eql(false);\n  // \texpect(\n  // \t\tcontainer.innerHTML\n  // \t).toEqual(\n  // \t\t('<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>')\n  // \t);\n  //\n  // \trender(template('bar'), container);\n  // \texpect(container.firstChild.children[ 0 ].selected).to.eql(false);\n  // \texpect(container.firstChild.children[ 1 ].selected).to.eql(true);\n  // \texpect(\n  // \t\tcontainer.innerHTML\n  // \t).toEqual(\n  // \t\t('<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>')\n  // \t);\n  // });\n\n  it('should render \"select\" boolean on select options #2 browser', () => {\n    const template = (val) =>\n      createElement(\n        'select',\n        {\n          multiple: true,\n          value: val,\n        },\n        createElement(\n          'option',\n          {\n            value: 'foo',\n          },\n          'foo',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'bar',\n          },\n          'bar',\n        ),\n      );\n\n    render(template('foo'), container);\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      // Missing selected markup\n      '<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>',\n    );\n  });\n\n  it('should populate the value attribute on select multiple using groups', () => {\n    const template = (val) =>\n      createElement(\n        'select',\n        {\n          multiple: true,\n          value: val,\n        },\n        createElement(\n          'optgroup',\n          { label: 'foo-group' },\n          createElement('option', { value: 'foo' }),\n        ),\n        createElement(\n          'optgroup',\n          { label: 'bar-group', disabled: true },\n          createElement('option', { value: 'bar' }),\n        ),\n      );\n\n    // render(template(undefined), container);\n    render(template(['foo', 'bar']), container);\n\n    expect(container.firstChild.children[0].disabled).toEqual(false);\n    expect(container.firstChild.children[1].disabled).toEqual(true);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].children[0].selected).toEqual(true);\n\n    render(template([]), container);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(\n      false,\n    );\n    expect(container.firstChild.children[1].children[0].selected).toEqual(\n      false,\n    );\n\n    render(template('foo'), container);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].children[0].selected).toEqual(\n      false,\n    );\n\n    render(template('bar'), container);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(\n      false,\n    );\n    expect(container.firstChild.children[1].children[0].selected).toEqual(true);\n\n    render(template(false), container);\n\n    expect(container.firstChild.childNodes[0].innerHTML).toEqual(\n      '<option value=\"foo\"></option>',\n    );\n    expect(container.firstChild.childNodes[1].innerHTML).toEqual(\n      '<option value=\"bar\"></option>',\n    );\n\n    expect(container.firstChild.children[0].children[0].selected).toEqual(\n      false,\n    );\n    expect(container.firstChild.children[1].children[0].selected).toEqual(\n      false,\n    );\n  });\n\n  it('should render \"select\" boolean on select options #3 browser', () => {\n    const template = (val) =>\n      createElement(\n        'select',\n        {\n          multiple: true,\n          value: val,\n        },\n        createElement(\n          'option',\n          {\n            value: 'foo',\n          },\n          'foo',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'bar',\n          },\n          'bar',\n        ),\n      );\n\n    render(template('bar'), container);\n\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>',\n    );\n\n    render(template(''), container);\n\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"foo\">foo</option><option value=\"bar\">bar</option></select>',\n    );\n  });\n\n  it('should assure a `textarea` with no value should show no value', () => {\n    render(createElement('textarea', null), container);\n    expect(container.firstChild.value).toEqual('');\n  });\n\n  it('should assure the value attribute also set the value property for `textarea`', () => {\n    const template = (val) =>\n      createElement('textarea', {\n        value: val,\n      });\n\n    render(template('foo'), container);\n    expect(container.firstChild.value).toEqual('foo');\n    render(template('bar'), container);\n    expect(container.firstChild.value).toEqual('bar');\n    render(template('bar'), container);\n    expect(container.firstChild.value).toEqual('bar');\n    render(template('foo'), container);\n    expect(container.firstChild.value).toEqual('foo');\n    render(template(null), container);\n    expect(container.firstChild.value).toEqual('');\n    render(template(undefined), container);\n    expect(container.firstChild.value).toEqual('');\n    render(template('bar'), container);\n    expect(container.firstChild.value).toEqual('bar');\n    render(template([]), container);\n    expect(container.firstChild.value).toEqual('');\n    render(template({}), container);\n    expect(container.firstChild.value).toEqual('[object Object]');\n  });\n\n  it('should handle when multiple values passed in as an array', () => {\n    const template = (val) =>\n      createElement(\n        'select',\n        {\n          multiple: true,\n          value: val,\n        },\n        createElement(\n          'option',\n          {\n            value: 'a',\n          },\n          'a',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'b',\n          },\n          'b',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'c',\n          },\n          'c',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'd',\n          },\n          'd',\n        ),\n      );\n    render(template(['a', 'b', 'c']), container);\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.firstChild.children[2].selected).toEqual(true);\n    expect(container.firstChild.children[3].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"a\">a</option><option value=\"b\">b</option><option value=\"c\">c</option><option value=\"d\">d</option></select>',\n    );\n  });\n\n  it('should handle when multiple options with selected set', () => {\n    const template = () =>\n      createElement(\n        'select',\n        {\n          multiple: true,\n        },\n        createElement(\n          'option',\n          {\n            value: 'a',\n            selected: true,\n          },\n          'a',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'b',\n            selected: true,\n          },\n          'b',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'c',\n            selected: true,\n          },\n          'c',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'd',\n          },\n          'd',\n        ),\n      );\n    render(template(), container);\n\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.firstChild.children[2].selected).toEqual(true);\n    expect(container.firstChild.children[3].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"a\">a</option><option value=\"b\">b</option><option value=\"c\">c</option><option value=\"d\">d</option></select>',\n    );\n  });\n\n  it('should render defaultValue', () => {\n    const template = () =>\n      createElement(\n        'select',\n        {\n          defaultValue: 'b',\n        },\n        createElement(\n          'option',\n          {\n            value: 'a',\n          },\n          'a',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'b',\n          },\n          'b',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'c',\n          },\n          'c',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'd',\n          },\n          'd',\n        ),\n      );\n    render(template(), container);\n\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.firstChild.children[2].selected).toEqual(false);\n    expect(container.firstChild.children[3].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select><option value=\"a\">a</option><option value=\"b\">b</option><option value=\"c\">c</option><option value=\"d\">d</option></select>',\n    );\n  });\n\n  it('should render multiple defaultValue', () => {\n    const template = () =>\n      createElement(\n        'select',\n        {\n          multiple: true,\n          defaultValue: ['a', 'b', 'c'],\n        },\n        createElement(\n          'option',\n          {\n            value: 'a',\n          },\n          'a',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'b',\n          },\n          'b',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'c',\n          },\n          'c',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'd',\n          },\n          'd',\n        ),\n      );\n    render(template(), container);\n\n    expect(container.firstChild.children[0].selected).toEqual(true);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n    expect(container.firstChild.children[2].selected).toEqual(true);\n    expect(container.firstChild.children[3].selected).toEqual(false);\n    expect(container.innerHTML).toBe(\n      '<select multiple=\"\"><option value=\"a\">a</option><option value=\"b\">b</option><option value=\"c\">c</option><option value=\"d\">d</option></select>',\n    );\n  });\n\n  it('should not touch selections, if value or selected, is null or undefined', () => {\n    render(\n      createElement(\n        'select',\n        null,\n        createElement(\n          'option',\n          {\n            value: 'a',\n          },\n          'a',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'b',\n          },\n          'b',\n        ),\n      ),\n      container,\n    );\n    container.firstChild.children[1].selected = true;\n    render(\n      createElement(\n        'select',\n        null,\n        createElement(\n          'option',\n          {\n            value: 'a',\n          },\n          'a',\n        ),\n        createElement(\n          'option',\n          {\n            value: 'b',\n          },\n          'b',\n        ),\n      ),\n      container,\n    );\n    expect(container.firstChild.children[0].selected).toEqual(false);\n    expect(container.firstChild.children[1].selected).toEqual(true);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/svg.ext.spec.js",
    "content": "import { render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('SVG (non-jsx)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n  });\n\n  afterEach(function () {\n    render(null, container);\n  });\n\n  it('should set attributes correctly', () => {\n    const template = (val1) => createElement('svg', { height: val1 });\n\n    render(template(null), container);\n    render(template(200), container);\n    expect(container.firstChild.tagName.toLowerCase()).toEqual('svg');\n    expect(container.firstChild.namespaceURI).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('height')).toEqual('200');\n    render(template(null), container);\n    render(template(200), container);\n    expect(container.firstChild.tagName.toLowerCase()).toEqual('svg');\n    expect(container.firstChild.namespaceURI).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('height')).toEqual('200');\n  });\n\n  it('should respect SVG namespace and render SVG attributes', () => {\n    let template;\n\n    template = (val1) =>\n      createElement(\n        'svg',\n        {\n          xmlns: 'http://www.w3.org/2000/svg',\n          version: '1.1',\n          baseProfile: 'full',\n          width: '200',\n          height: val1,\n        },\n        null,\n      );\n\n    render(template(200), container);\n    expect(container.firstChild.tagName.toLowerCase()).toEqual('svg');\n    expect(container.firstChild.namespaceURI).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('xmlns')).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('version')).toEqual('1.1');\n    expect(container.firstChild.getAttribute('baseProfile')).toEqual('full');\n    expect(container.firstChild.getAttribute('width')).toEqual('200');\n\n    render(template(null), container);\n\n    template = () => createElement('svg', { width: 200 }, null);\n    render(template(), container);\n\n    expect(container.firstChild.tagName.toLowerCase()).toEqual('svg');\n    expect(container.firstChild.namespaceURI).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('width')).toEqual('200');\n\n    render(template(), container);\n\n    expect(container.firstChild.tagName.toLowerCase()).toEqual('svg');\n    expect(container.firstChild.namespaceURI).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('width')).toEqual('200');\n  });\n\n  it('should set SVG as default namespace for <svg>', () => {\n    let template;\n\n    template = () => createElement('svg', null);\n\n    render(template(), container);\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    render(template(), container);\n\n    template = () => createElement('svg', null, createElement('path', null));\n\n    render(template(), container);\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n  });\n\n  it('should unset a namespaced attributes #1', () => {\n    const template = (val) =>\n      createElement('svg', null, createElement('image', { 'xlink:href': val }));\n\n    render(template(null), container);\n    render(template('test.jpg'), container);\n    expect(\n      container.firstChild.firstChild.getAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe('test.jpg');\n\n    render(template(null), container);\n    expect(\n      container.firstChild.firstChild.hasAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe(false);\n  });\n\n  it('should unset a namespaced attributes #2', () => {\n    const template = (val) =>\n      createElement('image', {\n        'xlink:href': val,\n      });\n\n    render(template(null), container);\n    expect(\n      container.firstChild.hasAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe(false);\n\n    render(template(null), container);\n    expect(\n      container.firstChild.hasAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe(false);\n  });\n\n  it('should unset a namespaced attributes #3', () => {\n    const template = (val) =>\n      createElement('svg', {\n        xmlns: 'http://www.w3.org/2000/svg',\n        'xlink:href': val,\n      });\n\n    render(template(null), container);\n    expect(\n      container.firstChild.hasAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe(false);\n\n    render(template('test.jpg'), container);\n    expect(\n      container.firstChild.getAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe('test.jpg');\n  });\n\n  it('should use the parent namespace by default (static)', () => {\n    let template;\n\n    template = () => createElement('svg', null, createElement('circle', null));\n\n    render(template(), container);\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n\n    render(template(), container);\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n\n    template = () => createElement('svg', null, createElement('path', null));\n\n    render(template(), container);\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n\n    template = () => createElement('svg', null);\n\n    render(template(), container);\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n  });\n\n  it('should handle SVG edge case (static)', () => {\n    const template = (child) =>\n      createElement('div', null, createElement('svg', null));\n\n    render(template(), container);\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    render(template(), container);\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n  });\n\n  it('should keep parent namespace (dynamic)', () => {\n    let child;\n    const template = (_child) =>\n      createElement(\n        'svg',\n        {\n          xmlns: 'http://www.w3.org/2000/svg',\n        },\n        _child,\n      );\n\n    child = () => createElement('circle', null);\n\n    render(template(child()), container);\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n\n    render(template(null), container);\n\n    child = () =>\n      createElement(\n        'circle',\n        {\n          xmlns: 'http://www.w3.org/2000/svg',\n        },\n        createElement('circle', {\n          xmlns: 'http://www.w3.org/2000/svg',\n        }),\n      );\n\n    render(template(child()), container);\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n\n    render(template(null), container);\n\n    child = () =>\n      createElement(\n        'circle',\n        null,\n        createElement(\n          'circle',\n          null,\n          createElement('g', {\n            xmlns: 'http://www.w3.org/2000/svg',\n          }),\n        ),\n      );\n\n    render(template(child()), container);\n    expect(container.firstChild.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(\n      container.firstChild.firstChild.firstChild.firstChild.namespaceURI,\n    ).toBe('http://www.w3.org/2000/svg');\n\n    child = () =>\n      createElement(\n        'circle',\n        null,\n        createElement(\n          'circle',\n          null,\n          createElement('g', null, createElement('g', null)),\n        ),\n      );\n    render(template(child()), container);\n    expect(\n      container.firstChild.firstChild.firstChild.firstChild.namespaceURI,\n    ).toBe('http://www.w3.org/2000/svg');\n\n    child = () =>\n      createElement(\n        'circle',\n        null,\n        createElement(\n          'circle',\n          null,\n          createElement(\n            'g',\n            null,\n            createElement('g', null, createElement('circle', null)),\n          ),\n        ),\n      );\n\n    render(template(null), container);\n    render(template(child()), container);\n    expect(\n      container.firstChild.firstChild.firstChild.firstChild.firstChild\n        .namespaceURI,\n    ).toBe('http://www.w3.org/2000/svg');\n    render(template(null), container);\n    render(template(child()), container);\n    expect(\n      container.firstChild.firstChild.firstChild.firstChild.firstChild\n        .namespaceURI,\n    ).toBe('http://www.w3.org/2000/svg');\n  });\n\n  it('should set class attribute', () => {\n    const template = (val) =>\n      createElement('image', {\n        class: val,\n      });\n\n    render(template('foo'), container);\n    expect(container.firstChild.getAttribute('class')).toBe('foo');\n    render(template(null), container);\n\n    render(template('bar'), container);\n    expect(container.firstChild.getAttribute('class')).toBe('bar');\n\n    render(template(['bar']), container);\n    expect(container.firstChild.getAttribute('class')).toBe('bar');\n\n    render(template(['bar', 'zoo']), container);\n    expect(container.firstChild.getAttribute('class')).toBe('bar,zoo');\n  });\n\n  it('should respect SVG namespace and render SVG attributes', () => {\n    const template = (val1, val2) =>\n      createElement('svg', {\n        xmlns: 'http://www.w3.org/2000/svg',\n        version: '1.1',\n        baseProfile: 'full',\n        width: val1,\n        height: val2,\n      });\n\n    render(template(200, 200), container);\n\n    expect(container.firstChild.tagName.toLowerCase()).toEqual('svg');\n    expect(container.firstChild.namespaceURI).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('xmlns')).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('version')).toEqual('1.1');\n    expect(container.firstChild.getAttribute('baseProfile')).toEqual('full');\n    expect(container.firstChild.getAttribute('width')).toEqual('200');\n    expect(container.firstChild.getAttribute('height')).toEqual('200');\n\n    render(template(300, 300), container);\n\n    expect(container.firstChild.tagName.toLowerCase()).toEqual('svg');\n    expect(container.firstChild.namespaceURI).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('xmlns')).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('version')).toEqual('1.1');\n    expect(container.firstChild.getAttribute('baseProfile')).toEqual('full');\n    expect(container.firstChild.getAttribute('width')).toEqual('300');\n    expect(container.firstChild.getAttribute('height')).toEqual('300');\n  });\n\n  it('should set \"viewBox\" attribute', () => {\n    const template = () =>\n      createElement('svg', {\n        xmlns: 'http://www.w3.org/2000/svg',\n        viewBox: '0 0 50 20',\n      });\n\n    render(template(), container);\n\n    expect(container.firstChild.tagName.toLowerCase()).toEqual('svg');\n    expect(container.firstChild.namespaceURI).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('xmlns')).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('viewBox')).toEqual('0 0 50 20');\n\n    render(template(), container);\n\n    expect(container.firstChild.tagName.toLowerCase()).toEqual('svg');\n    expect(container.firstChild.namespaceURI).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('xmlns')).toEqual(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.getAttribute('viewBox')).toEqual('0 0 50 20');\n  });\n\n  it('should solve SVG edge when wrapped inside a non-namespace element (static)', () => {\n    const template = () =>\n      createElement('div', null, createElement('svg', null));\n\n    render(template(), container);\n    // expect(container.firstChild.firstChild.tagName).toEqual('http://www.w3.org/2000/svg');\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n  });\n\n  it('should solve SVG edge case with XMLNS attribute when wrapped inside a non-namespace element (static)', () => {\n    const template = () =>\n      createElement(\n        'div',\n        {\n          xmlns: 'http://www.w3.org/2000/svg',\n        },\n        createElement('svg', null),\n      );\n\n    render(template(), container);\n    // expect(container.firstChild.firstChild.tagName).toEqual('http://www.w3.org/2000/svg');\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n  });\n\n  it('should solve SVG edge when wrapped inside a non-namespace element (static)', () => {\n    const template = () =>\n      createElement(\n        'div',\n        null,\n        createElement('svg', {\n          xmlns: 'http://www.w3.org/2000/svg',\n        }),\n      );\n\n    render(template(), container);\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    render(template(), container);\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n  });\n\n  it('should be possible to add className to SVG', () => {\n    const template = () =>\n      createElement('svg', {\n        xmlns: 'http://www.w3.org/2000/svg',\n        className: 'class1 class2',\n      });\n\n    render(template(), container);\n    expect(container.firstChild.getAttribute('class')).toBe('class1 class2');\n  });\n\n  it('should be possible to remove className from SVG', () => {\n    const template = (val) =>\n      createElement('svg', {\n        xmlns: 'http://www.w3.org/2000/svg',\n        className: val,\n      });\n\n    render(template('class1 class2'), container);\n    expect(container.firstChild.getAttribute('class')).toBe('class1 class2');\n    render(template('class1'), container);\n    expect(container.firstChild.getAttribute('class')).toBe('class1');\n    render(template(), container);\n    expect(container.firstChild.getAttribute('class')).toBe(null);\n  });\n\n  it('should follow last wins when both class and className are defined', () => {\n    const template = () =>\n      createElement('svg', {\n        xmlns: 'http://www.w3.org/2000/svg',\n        class: 'test',\n        className: 'class1 class2',\n      });\n\n    render(template(), container);\n    expect(container.firstChild.getAttribute('class')).toBe('class1 class2');\n  });\n\n  it('should respect XHTML namespace inside foreignObject of SVG', () => {\n    const template = (extraElement) =>\n      createElement(\n        'svg',\n        null,\n        createElement(\n          'foreignObject',\n          null,\n          createElement('div', null, extraElement ? createElement('p') : null),\n        ),\n      );\n\n    render(template(false), container);\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/1999/xhtml',\n    );\n    render(template(true), container);\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.firstChild.firstChild.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/1999/xhtml',\n    );\n    expect(\n      container.firstChild.firstChild.firstChild.firstChild.namespaceURI,\n    ).toBe('http://www.w3.org/1999/xhtml');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/svg.spec.jsx",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport { rerender } from '../../inferno-compat/src';\n\ndescribe('createTree - SVG (JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n  });\n\n  afterEach(function () {\n    render(null, container);\n  });\n\n  it('should render svg as <svg>', () => {\n    render(null, container);\n    render(<svg />, container);\n    expect(container.innerHTML).toBe('<svg></svg>');\n  });\n\n  it('should use the parent namespace by default', () => {\n    render(null, container);\n    render(\n      <svg xmlns=\"http://www.w3.org/2000/svg\">\n        <circle xmlns=\"http://www.w3.org/2000/svg\" />\n      </svg>,\n      container,\n    );\n    expect(container.firstChild.firstChild.tagName).toBe('circle');\n    expect(container.firstChild.getAttribute('xmlns')).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n\n    render(null, container);\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should keep parent namespace', () => {\n    render(\n      <svg xmlns=\"http://www.w3.org/2000/svg\">\n        <circle />\n      </svg>,\n      container,\n    );\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    render(null, container);\n    render(\n      <svg width=\"100\" height=\"100\">\n        <g>\n          <circle cx=\"50\" cy=\"50\" r=\"40\" stroke=\"green\" fill=\"yellow\" />\n        </g>\n        <g>\n          <g>\n            <circle cx=\"50\" cy=\"50\" r=\"40\" stroke=\"green\" fill=\"yellow\" />\n          </g>\n        </g>\n      </svg>,\n      container,\n    );\n    expect(container.childNodes[0].namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.childNodes[0].childNodes[0].tagName).toBe('g');\n    expect(container.childNodes[0].childNodes[0].namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.childNodes[0].childNodes[0].firstChild.tagName).toBe(\n      'circle',\n    );\n    expect(container.childNodes[0].childNodes[0].firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n\n    expect(container.childNodes[0].childNodes[1].tagName).toBe('g');\n    expect(container.childNodes[0].childNodes[1].namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.childNodes[0].childNodes[1].firstChild.tagName).toBe('g');\n    expect(container.childNodes[0].childNodes[1].firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(\n      container.childNodes[0].childNodes[1].firstChild.firstChild.tagName,\n    ).toBe('circle');\n    expect(\n      container.childNodes[0].childNodes[1].firstChild.firstChild.namespaceURI,\n    ).toBe('http://www.w3.org/2000/svg');\n\n    render(\n      <svg xmlns=\"http://www.w3.org/2000/svg\">\n        <circle />\n      </svg>,\n      container,\n    );\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n  });\n\n  it('should keep parent namespace with xmlns attribute', () => {\n    render(\n      <svg xmlns=\"http://www.w3.org/2000/svg\">\n        <circle />\n      </svg>,\n      container,\n    );\n    expect(container.firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n\n    render(\n      <svg width=\"100\" height=\"100\" xmlns=\"http://www.w3.org/2000/svg\">\n        <g>\n          <circle\n            xmlns=\"http://www.w3.org/2000/svg\"\n            cx=\"50\"\n            cy=\"50\"\n            r=\"40\"\n            stroke=\"green\"\n            fill=\"yellow\"\n          />\n        </g>\n        <g>\n          <circle\n            xmlns=\"http://www.w3.org/2000/svg\"\n            cx=\"50\"\n            cy=\"50\"\n            r=\"40\"\n            stroke=\"green\"\n            fill=\"yellow\"\n            foo={undefined}\n          />\n        </g>\n      </svg>,\n      container,\n    );\n    expect(container.childNodes[0].namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.childNodes[0].childNodes[0].tagName).toBe('g');\n    expect(container.childNodes[0].childNodes[0].namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.childNodes[0].childNodes[0].firstChild.tagName).toBe(\n      'circle',\n    );\n    expect(\n      container.childNodes[0].childNodes[0].firstChild.getAttribute('xmlns'),\n    ).toBe('http://www.w3.org/2000/svg');\n    expect(container.childNodes[0].childNodes[0].firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n\n    expect(container.childNodes[0].childNodes[1].tagName).toBe('g');\n    expect(container.childNodes[0].childNodes[1].namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n    expect(container.childNodes[0].childNodes[1].firstChild.tagName).toBe(\n      'circle',\n    );\n    expect(\n      container.childNodes[0].childNodes[1].firstChild.getAttribute('xmlns'),\n    ).toBe('http://www.w3.org/2000/svg');\n    expect(container.childNodes[0].childNodes[1].firstChild.namespaceURI).toBe(\n      'http://www.w3.org/2000/svg',\n    );\n  });\n\n  it('should set and remove dynamic class property', () => {\n    const value = 'foo';\n\n    render(<svg className={value} />, container);\n\n    expect(container.firstChild.tagName).toEqual('svg');\n    expect(container.firstChild.getAttribute('class')).toBe('foo');\n\n    render(<svg />, container);\n\n    expect(container.firstChild.tagName).toEqual('svg');\n    expect(container.firstChild.hasAttribute('class')).toBe(false);\n  });\n\n  it('should set and remove dynamic class attribute', () => {\n    const value = 'foo';\n\n    render(<svg className={value} />, container);\n\n    expect(container.firstChild.tagName).toEqual('svg');\n    expect(container.firstChild.getAttribute('class')).toBe('foo');\n\n    render(<svg />, container);\n\n    expect(container.firstChild.tagName).toEqual('svg');\n    expect(container.firstChild.hasAttribute('class')).toBe(false);\n  });\n\n  it('should set static class attribute, update to dynamic attr, and remove', () => {\n    render(<svg className={null} />, container);\n    render(<svg className={{}} />, container);\n    render(<svg className=\"bar\" />, container);\n\n    expect(container.firstChild.tagName).toEqual('svg');\n    expect(container.firstChild.getAttribute('class')).toBe('bar');\n\n    const value = 'foo';\n\n    render(<svg className={value} />, container);\n    expect(container.firstChild.tagName).toEqual('svg');\n    expect(container.firstChild.getAttribute('class')).toBe('foo');\n\n    render(<svg />, container);\n\n    expect(container.firstChild.tagName).toEqual('svg');\n    expect(container.firstChild.hasAttribute('class')).toBe(false);\n  });\n\n  it('should remove arbitrary SVG camel case attributes', () => {\n    render(<svg theWord=\"theBird\" />, container);\n\n    expect(container.firstChild.hasAttribute('theWord')).toBe(true);\n    render(<svg />, container);\n    expect(container.firstChild.hasAttribute('theWord')).toBe(false);\n  });\n\n  it('should remove namespaced SVG attributes', () => {\n    render(<svg clip-path=\"0 0 110 110\" />, container);\n\n    expect(container.firstChild.tagName).toEqual('svg');\n\n    expect(container.firstChild.hasAttribute('clip-path')).toBe(true);\n\n    render(\n      <svg>\n        <image />\n      </svg>,\n      container,\n    );\n\n    expect(\n      container.firstChild.firstChild.hasAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe(false);\n  });\n\n  it('should remove namespaced SVG attributes', () => {\n    render(<svg clip-path=\"0 0 110 110\" />, container);\n\n    expect(container.firstChild.tagName).toEqual('svg');\n\n    expect(container.firstChild.hasAttribute('clip-path')).toBe(true);\n\n    render(\n      <svg>\n        <image />\n      </svg>,\n      container,\n    );\n\n    expect(\n      container.firstChild.firstChild.hasAttributeNS(\n        'http://www.w3.org/1999/xlink',\n        'href',\n      ),\n    ).toBe(false);\n  });\n\n  it('Should make SVG and children with spread attribute', () => {\n    const spread = { id: 'test' };\n\n    render(<svg {...spread} />, container);\n    expect(container.innerHTML).toBe('<svg id=\"test\"></svg>');\n  });\n\n  describe('SVG elements', () => {\n    it('Should keep SVG children flagged when parent is SVG', () => {\n      class Rect extends Component {\n        constructor(p, c) {\n          super(p, c);\n          this.state = { className: 'foo' };\n        }\n\n        componentDidMount() {\n          this.setState({ className: 'bar' });\n        }\n\n        render() {\n          return createElement('rect', {\n            className: this.state.className,\n          });\n        }\n      }\n\n      render(\n        <svg>\n          <Rect />\n        </svg>,\n        container,\n      );\n\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe('foo');\n\n      rerender();\n\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe('bar');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/text.spec.js",
    "content": "import { render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('Text', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n  });\n\n  afterEach(function () {\n    render(null, container);\n  });\n\n  const emptyDefinitions = [\n    {\n      name: 'normal text',\n      value: 'Hello, World!',\n      expected: 'Hello, World!',\n    },\n    {\n      name: 'number value (cast to string)',\n      value: 123,\n      expected: '123',\n    },\n    {\n      name: 'number value (Addition)',\n      value: 123 + 123,\n      expected: '246',\n    },\n    {\n      name: 'number value (subtraction)',\n      value: 123 - 122,\n      expected: '1',\n    },\n    {\n      name: 'number value (Associative of Addition)',\n      value: '(a + b) + c = a + (b + c)',\n      expected: '(a + b) + c = a + (b + c)',\n    },\n    {\n      name: 'number and text',\n      value: 123 + 'Hello',\n      expected: '123Hello',\n    },\n    {\n      name: 'number',\n      value: '123',\n      expected: '123',\n    },\n    {\n      name: 'math',\n      value: 44 - 44 * 3 - 333,\n      expected: '-421',\n    },\n    {\n      name: 'chinese',\n      value: '您好',\n      expected: '您好',\n    },\n    {\n      name: 'multiple whitespace',\n      value: '         ',\n      expected: '         ',\n    },\n    {\n      name: 'multiple whitespace and single number',\n      value: '         ' + 123,\n      expected: '         123',\n    },\n    {\n      name: 'empty string with whitespace',\n      value: ' ',\n      expected: ' ',\n    },\n    {\n      name: 'empty string with double whitespace',\n      value: '  ',\n      expected: '  ',\n    },\n    {\n      name: 'empty string with triple whitespaces',\n      value: '   ',\n      expected: '   ',\n    },\n    {\n      name: 'empty string with one whitespace to left',\n      value: ' a',\n      expected: ' a',\n    },\n    {\n      name: 'empty string with triple whitespaces to left',\n      value: '   a',\n      expected: '   a',\n    },\n  ];\n\n  for (const arg of emptyDefinitions) {\n    const template = () => createElement('div', null, arg.value);\n\n    it('should create a static text node with ' + arg.name, () => {\n      render(template(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.childNodes.length).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n\n      render(template(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.childNodes.length).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n    });\n\n    const template2 = () => createElement('div', null, null);\n\n    it('should create a static text node with null', () => {\n      render(template2(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.childNodes.length).toBe(1);\n      expect(container.firstChild.textContent).toBe('');\n\n      render(template2(), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.childNodes.length).toBe(1);\n      expect(container.firstChild.textContent).toBe('');\n    });\n\n    const template3 = (text) => createElement('div', null, text);\n\n    it(`should create a dynamic text node with ${arg.name} - text property 1`, () => {\n      render(template3(arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.childNodes.length).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n\n      render(template3(arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.childNodes.length).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n    });\n\n    it(`should create a dynamic text node with ${arg.name} - text property 2`, () => {\n      render(template3(null), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.childNodes.length).toBe(1);\n      expect(container.firstChild.textContent).toBe('');\n\n      render(template3(arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.childNodes.length).toBe(1);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n    });\n\n    const template4 = (text) =>\n      createElement('div', null, createElement('span', null, text));\n\n    it(\n      'should create a dynamic text node with ' +\n        arg.name +\n        ' - children node text',\n      () => {\n        render(template4(arg.value), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.firstChild.textContent).toBe(arg.expected);\n\n        render(template4(arg.value), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.firstChild.textContent).toBe(arg.expected);\n      },\n    );\n\n    const template5 = (text) => createElement('div', null, text);\n\n    it(\n      'should create a dynamic text node with ' +\n        arg.name +\n        ' - single child with text ',\n      () => {\n        render(template5(arg.value), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe(arg.expected);\n\n        render(template5(arg.value), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe(arg.expected);\n      },\n    );\n\n    const template6 = (text) =>\n      createElement('div', null, createElement('span', null, text));\n\n    it(\n      'should create a dynamic text node with ' +\n        arg.name +\n        ' - deep child with text property ',\n      () => {\n        render(template6(arg.value), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe(arg.expected);\n\n        render(template6(arg.value), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe(arg.expected);\n      },\n    );\n\n    const template7 = (text) =>\n      createElement(\n        'div',\n        null,\n        createElement('span', null, createElement('b', null, text)),\n      );\n\n    it(\n      'should create a dynamic text node with ' +\n        arg.name +\n        ' - deeper child with text property',\n      () => {\n        render(template7(arg.value), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe(arg.expected);\n\n        render(template7(arg.value), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe(arg.expected);\n      },\n    );\n\n    it(\n      'should create a dynamic text node with ' +\n        arg.name +\n        ' - deeper child with text property',\n      () => {\n        render(template7(null), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe('');\n\n        render(template7(arg.value), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe(arg.expected);\n      },\n    );\n\n    it(\n      'should create a dynamic text node with ' +\n        arg.name +\n        ' - deeper child with text property',\n      () => {\n        render(template7(arg.value), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe(arg.expected);\n\n        render(template7(null), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe('');\n      },\n    );\n\n    it(\n      'should create a dynamic text node with ' +\n        arg.name +\n        ' - deeper child with text property',\n      () => {\n        render(template7(null), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe('');\n\n        render(template7(null), container);\n        expect(container.firstChild.nodeType).toBe(1);\n        expect(container.childNodes.length).toBe(1);\n        expect(container.firstChild.childNodes.length).toBe(1);\n        expect(container.firstChild.textContent).toBe('');\n      },\n    );\n  }\n\n  const multiArray = [\n    {\n      name: 'multiple text',\n      value: ['Hello', ' World'],\n      expected: 'Hello World',\n      children: 2,\n    },\n    {\n      name: 'multiple numbers (cast to string)',\n      value: ['12', '3'],\n      expected: '123',\n      children: 2,\n    },\n    {\n      name: 'multiple numbers',\n      value: [12, 3],\n      expected: '123',\n      children: 2,\n    },\n    {\n      name: 'null value',\n      value: null,\n      expected: '',\n      children: 0,\n    },\n    {\n      name: 'undefined value',\n      value: undefined,\n      expected: '',\n      children: 0,\n    },\n    {\n      name: 'empty string',\n      value: '',\n      expected: '',\n      children: 0,\n    },\n    {\n      name: 'string with whitespace',\n      value: ' ',\n      expected: ' ',\n      children: 1,\n    },\n    {\n      name: 'string as null',\n      value: null,\n      expected: '',\n      children: 0,\n    },\n    {\n      name: 'string as undefined',\n      value: null,\n      expected: '',\n      children: 0,\n    },\n    {\n      name: 'empty array',\n      value: [],\n      expected: '',\n      children: 0,\n    },\n    {\n      name: 'number',\n      value: 123,\n      expected: '123',\n      children: 1,\n    },\n    {\n      name: 'multiple numbers (Addition)',\n      value: [12 + 3, 3],\n      expected: '153',\n      children: 2,\n    },\n    {\n      name: 'multiple numbers (subtraction)',\n      value: [12 - 3, 3],\n      expected: '93',\n      children: 2,\n    },\n    {\n      name: 'multiple numbers (math)',\n      value: [12 - 3 - 3 * 4 - 1],\n      expected: '-4',\n      children: 1,\n    },\n    {\n      name: 'multiple numbers (mixed math)',\n      value: [12 - 3, 3 * 4 - 1],\n      expected: '911',\n      children: 2,\n    },\n  ];\n\n  for (const arg of multiArray) {\n    const template1 = (textVar) => createElement('div', null, textVar);\n\n    it('should create a children property with ' + arg.name, () => {\n      render(template1(arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.childNodes.length).toBe(1);\n      expect(container.firstChild.childNodes.length).toBe(arg.children);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n\n      render(template1(arg.value), container);\n      expect(container.firstChild.nodeType).toBe(1);\n      expect(container.childNodes.length).toBe(1);\n      expect(container.firstChild.childNodes.length).toBe(arg.children);\n      expect(container.firstChild.textContent).toBe(arg.expected);\n    });\n  }\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/update.ext.spec.js",
    "content": "import { render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('Update (non-jsx)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n  });\n\n  afterEach(function () {\n    render(null, container);\n  });\n\n  it('should insert an additionnal tag node', () => {\n    const template = (child) => createElement('div', null, child);\n    let span;\n\n    span = () => createElement('div', null, 'hello ', 'to');\n\n    render(template(span()), container);\n\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.textContent).toBe('hello to');\n\n    render(template(span()), container);\n\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.textContent).toBe('hello to');\n\n    span = () => createElement('div', null);\n\n    render(template(span()), container);\n\n    expect(container.firstChild.nodeName).toBe('DIV');\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.textContent).toBe('');\n  });\n\n  it('should insert an additional tag node', () => {\n    const template = (child) => createElement('div', null, child);\n    const span = () => createElement('span', null);\n\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe('<span></span>');\n    render(template(null), container);\n    expect(container.firstChild.innerHTML).toBe('');\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe('<span></span>');\n  });\n\n  it('should insert an additional tag node', () => {\n    const template = (child) => createElement('div', null, child);\n    const div = () => createElement('div', null);\n\n    render(template(null), container);\n    expect(container.firstChild.innerHTML).toBe('');\n    render(template(div()), container);\n    expect(container.firstChild.innerHTML).toBe('<div></div>');\n  });\n\n  it('should insert an additional tag node', () => {\n    const template = (child) => createElement('div', null, child);\n    // const span = () => createElement('div');\n\n    render(template(null), container);\n    expect(container.firstChild.innerHTML).toBe('');\n    render(template(null), container);\n    expect(container.firstChild.innerHTML).toBe('');\n  });\n\n  it('should insert multiple additional tag node', () => {\n    const template = (child) => createElement('div', null, child);\n    const span = () => createElement('div', null);\n\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe('<div></div>');\n  });\n\n  it('should render a node with dynamic values', () => {\n    const template = (val1, val2) =>\n      createElement('div', null, 'Hello world - ', val1, ' ', val2);\n\n    render(template('Inferno', 'Owns'), container);\n    expect(container.innerHTML).toBe('<div>Hello world - Inferno Owns</div>');\n    render(template('Inferno', 'Owns'), container);\n    expect(container.innerHTML).toBe('<div>Hello world - Inferno Owns</div>');\n\n    render(template('Inferno', null), container);\n    expect(container.innerHTML).toBe('<div>Hello world - Inferno </div>');\n\n    render(template(null, 'Owns'), container);\n    expect(container.innerHTML).toBe('<div>Hello world -  Owns</div>');\n\n    render(template(null), container);\n    expect(container.innerHTML).toBe('<div>Hello world -  </div>');\n\n    render(template(undefined), container);\n    expect(container.innerHTML).toBe('<div>Hello world -  </div>');\n\n    render(template(null, 'Owns'), container);\n    expect(container.innerHTML).toBe('<div>Hello world -  Owns</div>');\n\n    render(template('Test', 'Works!'), container);\n    expect(container.innerHTML).toBe('<div>Hello world - Test Works!</div>');\n  });\n\n  it('should update a wrapped text node', () => {\n    const template = (val1, val2) =>\n      createElement('div', null, val1, ' foo', val2);\n\n    render(template(null), container);\n    expect(container.innerHTML).toBe('<div> foo</div>');\n\n    render(template('Hello', 'Bar'), container);\n    expect(container.innerHTML).toBe('<div>Hello fooBar</div>');\n\n    render(template(undefined), container);\n    expect(container.innerHTML).toBe('<div> foo</div>');\n\n    render(template('The', ' is dead!'), container);\n    expect(container.innerHTML).toBe('<div>The foo is dead!</div>');\n  });\n\n  it('should update a wrapped text node', () => {\n    const template = (val1, val2) =>\n      createElement('div', null, val1, ' foo', val2);\n\n    render(template(null), container);\n    expect(container.innerHTML).toBe('<div> foo</div>');\n\n    render(template(undefined), container);\n    expect(container.innerHTML).toBe('<div> foo</div>');\n\n    render(template('Hello', 'Bar'), container);\n    expect(container.innerHTML).toBe('<div>Hello fooBar</div>');\n\n    render(template('Hello', null), container);\n    expect(container.innerHTML).toBe('<div>Hello foo</div>');\n\n    render(template(null, 'Bar'), container);\n    expect(container.innerHTML).toBe('<div> fooBar</div>');\n\n    render(template(undefined), container);\n    expect(container.innerHTML).toBe('<div> foo</div>');\n\n    render(template('The', ' is dead!'), container);\n    expect(container.innerHTML).toBe('<div>The foo is dead!</div>');\n  });\n\n  it('should update a wrapped text node with 4 arguments', () => {\n    const template = (val1, val2, val3, val4) =>\n      createElement('div', null, val1, val2, val3, val4);\n\n    render(template('Hello', ' world!', ' and ', 'Bar'), container);\n    expect(container.innerHTML).toBe('<div>Hello world! and Bar</div>');\n\n    render(template(null, null, null, null), container);\n    expect(container.innerHTML).toBe('<div></div>');\n\n    render(template(), container);\n    expect(container.innerHTML).toBe('<div></div>');\n\n    render(template('Hello', ' world!', ' and ', 'Zoo'), container);\n    expect(container.innerHTML).toBe('<div>Hello world! and Zoo</div>');\n\n    render(template('Hello', null, ' and ', 'Zoo'), container);\n    expect(container.innerHTML).toBe('<div>Hello and Zoo</div>');\n\n    expect(() => {\n      render(template('Hello', {}, ' and ', 'Zoo'), container);\n    }).toThrow();\n\n    render(template('Hello', ' poz', ' and ', 'Zoo'), container);\n    expect(container.innerHTML).toBe('<div>Hello poz and Zoo</div>');\n\n    render(template('The ', 'bar', ' is', ' is dead!'), container);\n    expect(container.innerHTML).toBe('<div>The bar is is dead!</div>');\n\n    render(template('Hello', ' world!', null), container);\n    expect(container.innerHTML).toBe('<div>Hello world!</div>');\n  });\n\n  it('should update a node with static text', () => {\n    const template = (val) =>\n      createElement(\n        'div',\n        {\n          id: val,\n        },\n        'Hello, World',\n      );\n\n    render(template('Hello'), container);\n    expect(container.innerHTML).toBe('<div id=\"Hello\">Hello, World</div>');\n\n    render(template('Bar'), container);\n    expect(container.innerHTML).toBe('<div id=\"Bar\">Hello, World</div>');\n\n    render(template(), container);\n    expect(container.innerHTML).toBe('<div>Hello, World</div>');\n\n    render(template(), container);\n    expect(container.innerHTML).toBe('<div>Hello, World</div>');\n\n    render(template(null), container);\n    expect(container.innerHTML).toBe('<div>Hello, World</div>');\n\n    render(template(null), container);\n    expect(container.innerHTML).toBe('<div>Hello, World</div>');\n\n    render(template('foo'), container);\n    expect(container.innerHTML).toBe('<div id=\"foo\">Hello, World</div>');\n  });\n\n  it('should update a node with multiple children and static text', () => {\n    const template = (val1) =>\n      createElement(\n        'div',\n        {\n          id: val1,\n        },\n        'Hello, World',\n      );\n\n    render(template('Hello'), container);\n    expect(container.innerHTML).toBe('<div id=\"Hello\">Hello, World</div>');\n\n    render(template('Hello'), container);\n    expect(container.innerHTML).toBe('<div id=\"Hello\">Hello, World</div>');\n\n    render(template(null), container); // should unset\n    expect(container.innerHTML).toBe('<div>Hello, World</div>');\n\n    render(template('foo'), container);\n    expect(container.innerHTML).toBe('<div id=\"foo\">Hello, World</div>');\n  });\n\n  it('should update a node with multiple children and static text #2', () => {\n    const template = (val1) =>\n      createElement(\n        'div',\n        {\n          id: val1,\n        },\n        'Hello, World',\n      );\n\n    render(template(null), container); // should unset\n    expect(container.innerHTML).toBe('<div>Hello, World</div>');\n\n    render(template('Hello'), container);\n    expect(container.innerHTML).toBe('<div id=\"Hello\">Hello, World</div>');\n\n    render(template(undefined), container); // should unset\n    expect(container.innerHTML).toBe('<div>Hello, World</div>');\n\n    render(template('foo'), container);\n    expect(container.innerHTML).toBe('<div id=\"foo\">Hello, World</div>');\n\n    render(template(), container); // should unset\n    expect(container.innerHTML).toBe('<div>Hello, World</div>');\n  });\n\n  it('should update a div with class attribute, and dynamic children with static text', () => {\n    const template = (child) =>\n      createElement(\n        'div',\n        {\n          class: 'hello, world',\n        },\n        child,\n      );\n\n    const spanList = () => createElement('span', null, '1', '2', '3');\n\n    const span = (_b) => createElement('span', null, _b);\n\n    render(template(null), container);\n\n    expect(container.firstChild.nodeType).toBe(1);\n    expect(container.firstChild.childNodes.length).toBe(0);\n    expect(container.firstChild.tagName).toBe('DIV');\n\n    render(template(span(spanList())), container);\n    expect(container.firstChild.nodeType).toBe(1);\n    expect(container.firstChild.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.firstChild.firstChild.childNodes.length).toBe(\n      3,\n    );\n    expect(container.firstChild.tagName).toBe('DIV');\n\n    render(template(span(null)), container);\n\n    expect(container.firstChild.nodeType).toBe(1);\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.tagName).toBe('DIV');\n  });\n\n  it('should handle lots of dynamic variables', () => {\n    const template = function (val1, val2, val3, val4, val5, val6) {\n      return createElement(\n        'div',\n        {\n          className: val2,\n          id: val1,\n        },\n        createElement(\n          'div',\n          {\n            id: val5,\n          },\n          createElement('span', null, val6),\n        ),\n        createElement(\n          'div',\n          {\n            className: val4,\n          },\n          val3,\n        ),\n      );\n    };\n\n    render(template(), container);\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe(null);\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('');\n\n    render(template('foo1', 'bar1', 'foo2', 'bar2', 'foo3', 'bar3'), container);\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe('bar1');\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('bar3');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('bar3');\n\n    render(template('foo1', 'foo2', 'bar2', 'foo3', 'bar3'), container);\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe('foo2');\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('');\n\n    render(template(null), container);\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe(null);\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('');\n\n    render(template(undefined), container);\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe(null);\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('');\n\n    render(template('yar1', 'noo1', [], 'noo2', 'yar3', 'noo3'), container);\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe('noo1');\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('noo3');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('noo3');\n\n    render(template('yar1', 'noo1', [], 'noo2', 'yar3', 123), container);\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe('noo1');\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('123');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('123');\n\n    render(template('yar1', 'noo1', 'yar2', 'noo2', 'yar3', 'noo3'), container);\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe('noo1');\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('noo3');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('noo3');\n\n    render(template('yar1', null, 'yar2', 'noo2', 'yar3', null), container);\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe(null);\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('');\n\n    render(template('yar1', null, null, 'noo2', null, null), container);\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe(null);\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('');\n\n    render(template([], null, null, [], null, null), container);\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe(null);\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('');\n\n    render(template([], [], 123, [], null, null), container);\n\n    expect(container.firstChild.firstChild.tagName).toBe('DIV');\n    expect(container.firstChild.getAttribute('class')).toBe('');\n    expect(container.firstChild.firstChild.firstChild.tagName).toBe('SPAN');\n    expect(container.firstChild.firstChild.textContent).toBe('');\n    expect(container.firstChild.firstChild.firstChild.textContent).toBe('');\n  });\n\n  it('should render a basic example #7', () => {\n    const div = (child) => createElement('div', null, child);\n    const span1 = () => 'Hello world!';\n\n    render(div(span1()), container);\n    expect(container.innerHTML).toBe('<div>Hello world!</div>');\n    const span2 = (child) => createElement('span', null, 'Im updated!');\n\n    render(div(span2()), container);\n  });\n\n  it('should patch a wrapped text node with its container', () => {\n    const template = (child) => createElement('div', null, child);\n\n    render(template(null), container);\n    expect(container.innerHTML).toBe('<div></div>');\n\n    render(template(null), container);\n    expect(container.innerHTML).toBe('<div></div>');\n    const span = () => createElement('div', null, 'Hello');\n\n    render(template(span()), container);\n    expect(container.innerHTML).toBe('<div><div>Hello</div></div>');\n  });\n\n  it('should patch a text node into a tag node', () => {\n    const template = (child) => createElement('div', null, child);\n    const span = function () {\n      return 'Hello';\n    };\n\n    render(template(span()), container);\n    expect(container.innerHTML).toBe('<div>Hello</div>');\n  });\n\n  it('should patch a tag node into a text node #2', () => {\n    const template = (child) => createElement('div', null, child);\n\n    const span = () => createElement('span', null, 'Good bye!');\n    render(template(span()), container);\n    expect(container.innerHTML).toBe('<div><span>Good bye!</span></div>');\n\n    render(template(), container);\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  it('should render text then update it', () => {\n    const template = (child) => createElement('div', null, child);\n    const span = function () {\n      return 'Hello';\n    };\n\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe('Hello');\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe('Hello');\n  });\n\n  it('should render text then update to an array of text nodes', () => {\n    const template = (child) => createElement('div', null, child);\n    const span = function () {\n      return createElement('span', null, 'Hello ', 'World', '!');\n    };\n\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe('<span>Hello World!</span>');\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe('<span>Hello World!</span>');\n  });\n\n  it('should render an array of text nodes then update to a single text node', () => {\n    const template = (child) => createElement('div', null, child);\n    const span = function () {\n      return createElement('span', null, 'Hello ', 'World', '!');\n    };\n\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe('<span>Hello World!</span>');\n  });\n\n  it('should update and array of text nodes to another array of text nodes', () => {\n    const template = (child) => createElement('div', null, child);\n    const span = function () {\n      return createElement('span', null, 'Hello ', 'World');\n    };\n\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe('<span>Hello World</span>');\n  });\n\n  it('should update and array of text nodes to another array of text nodes #2', () => {\n    const template = (child) => createElement('div', null, child);\n    const span = function () {\n      return createElement('span', null, 'Hello ', 'World', '!');\n    };\n\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe('<span>Hello World!</span>');\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe('<span>Hello World!</span>');\n  });\n\n  it('should update an node with static child', () => {\n    const template = (child) =>\n      createElement(\n        'div',\n        null,\n        createElement(\n          'div',\n          null,\n          createElement('span', {\n            id: child,\n          }),\n        ),\n      );\n\n    render(template('id#1'), container);\n    expect(container.firstChild.innerHTML).toBe(\n      '<div><span id=\"id#1\"></span></div>',\n    );\n\n    render(template('id#2'), container);\n    expect(container.firstChild.innerHTML).toBe(\n      '<div><span id=\"id#2\"></span></div>',\n    );\n    render(template('id#3'), container);\n    expect(container.firstChild.innerHTML).toBe(\n      '<div><span id=\"id#3\"></span></div>',\n    );\n  });\n\n  it('should update an node with static child and dynamic custom attribute', () => {\n    const template = (child) =>\n      createElement('div', null, createElement('div', null, child));\n    const span = function (val) {\n      return createElement('span', {\n        custom_attr: val,\n      });\n    };\n\n    render(template(span('id#1')), container);\n    expect(container.firstChild.innerHTML).toBe(\n      '<div><span custom_attr=\"id#1\"></span></div>',\n    );\n    render(template(span('id#1')), container);\n    expect(container.firstChild.innerHTML).toBe(\n      '<div><span custom_attr=\"id#1\"></span></div>',\n    );\n  });\n\n  it('should update an node with static child and dynamic custom attribute and static text', () => {\n    const template = (child) =>\n      createElement('div', null, createElement('div', null, child));\n    const span = function (val) {\n      return createElement(\n        'span',\n        {\n          custom_attr: val,\n        },\n        'Hello!!',\n      );\n    };\n\n    render(template(span('id#1')), container);\n    expect(container.firstChild.innerHTML).toBe(\n      '<div><span custom_attr=\"id#1\">Hello!!</span></div>',\n    );\n    render(template(span('id#2')), container);\n    expect(container.firstChild.innerHTML).toBe(\n      '<div><span custom_attr=\"id#2\">Hello!!</span></div>',\n    );\n  });\n\n  it('should update an node with static child and dynamic custom attribute and static text #2', () => {\n    const template = (child) =>\n      createElement('div', null, createElement('div', null, child));\n    const span = function (val) {\n      return createElement(\n        'span',\n        {\n          custom_attr: val,\n        },\n        'Hello!!',\n      );\n    };\n\n    render(template(span('id#1')), container);\n    expect(container.firstChild.innerHTML).toBe(\n      '<div><span custom_attr=\"id#1\">Hello!!</span></div>',\n    );\n  });\n\n  it('should not ignore a empty text node', () => {\n    const template = () => createElement('span', null, '');\n\n    render(template(), container);\n    expect(container.childNodes.length).toBe(1);\n    render(template(), container);\n    expect(container.childNodes.length).toBe(1);\n  });\n\n  it('should remove a text node', () => {\n    const template = (child) => createElement('div', null, child);\n\n    render(template(['hello', 'world']), container);\n    expect(container.firstChild.childNodes.length).toBe(2);\n  });\n\n  it('should update multiple changes', () => {\n    const template = (val1, val2) =>\n      createElement(\n        'div',\n        {\n          className: val1,\n        },\n        val2,\n      );\n\n    render(template('hello', ['hello', 'world']), container);\n    expect(container.firstChild.childNodes.length).toBe(2);\n    expect(container.firstChild.getAttribute('class')).toBe('hello');\n\n    render(template('good bye', ['hello']), container);\n    expect(container.firstChild.childNodes.length).toBe(1);\n    expect(container.firstChild.getAttribute('class')).toBe('good bye');\n  });\n\n  it('should update an node with static child and text', () => {\n    const template = () =>\n      createElement('div', null, createElement('div', null, 'Hello, World'));\n\n    render(template(), container);\n    expect(container.firstChild.innerHTML).toBe('<div>Hello, World</div>');\n    render(template(), container);\n    expect(container.firstChild.innerHTML).toBe('<div>Hello, World</div>');\n\n    render(template(), container);\n    expect(container.firstChild.innerHTML).toBe('<div>Hello, World</div>');\n  });\n\n  it('should update an node with dynamic child', () => {\n    const template = (child) =>\n      createElement('div', null, createElement('div', null, child));\n    const span = function () {\n      return createElement('span', null, 'Hello ', 'World');\n    };\n    render(template(span()), container);\n    expect(container.firstChild.innerHTML).toBe(\n      '<div><span>Hello World</span></div>',\n    );\n  });\n\n  it('should inject dynamic text various places', () => {\n    const div = (text) =>\n      createElement('div', null, 'There is ', text, ' spoon!');\n\n    render(div('no'), container);\n    expect(container.innerHTML).toBe('<div>There is no spoon!</div>');\n\n    render(div('one'), container);\n    expect(container.innerHTML).toBe('<div>There is one spoon!</div>');\n\n    render(div(), container);\n    expect(container.innerHTML).toBe('<div>There is  spoon!</div>');\n\n    render(div(null), container);\n    expect(container.innerHTML).toBe('<div>There is  spoon!</div>');\n\n    render(div(undefined), container);\n    expect(container.innerHTML).toBe('<div>There is  spoon!</div>');\n  });\n\n  it('should render a div tag and remove styling', () => {\n    let template;\n\n    template = (styleRule) =>\n      createElement('div', {\n        style: styleRule,\n      });\n\n    render(\n      template({\n        color: 'red',\n        'padding-left': '10px',\n      }),\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div style=\"color: red; padding-left: 10px;\"></div>',\n    );\n\n    render(template(null), container);\n\n    expect([null, '']).toContain(container.firstChild.getAttribute('style'));\n  });\n\n  if (typeof global !== 'undefined' && !global.usingJSDOM) {\n    describe('should render styling on root node, and set and remove styling on multiple children', () => {\n      let template;\n\n      template = (styleRule) =>\n        createElement(\n          'div',\n          {\n            style: {\n              width: '200px',\n            },\n          },\n          createElement(\n            'div',\n            {\n              class: 'Hello, world!',\n            },\n            createElement('div', {\n              style: styleRule,\n            }),\n          ),\n        );\n\n      it('Initial render (creation)', () => {\n        render(\n          template({\n            color: 'red',\n            'padding-top': '10px',\n          }),\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div style=\"width: 200px;\"><div class=\"Hello, world!\"><div style=\"color: red; padding-top: 10px;\"></div></div></div>',\n        );\n        render(\n          template({\n            color: 'red',\n            'padding-left': '10px',\n          }),\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div style=\"width: 200px;\"><div class=\"Hello, world!\"><div style=\"color: red; padding-left: 10px;\"></div></div></div>',\n        );\n      });\n\n      it('Second render (update)', () => {\n        render(template(null), container); // change style to null\n\n        expect([null, '']).toContain(\n          container.firstChild.firstChild.getAttribute('style'),\n        );\n      });\n\n      it('Third render (update)', () => {\n        render(\n          template({\n            color: 'blue',\n            'margin-bottom': '20px',\n          }),\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div style=\"width: 200px;\"><div class=\"Hello, world!\"><div style=\"color: blue; margin-bottom: 20px;\"></div></div></div>',\n        );\n      });\n    });\n  }\n\n  describe('Github #142', () => {\n    describe('nonKeyed updates', () => {\n      it('variation 1', () => {\n        function A() {\n          return createElement(\n            'div',\n            null,\n            createElement(\n              'div',\n              null,\n              createElement(\n                'table',\n                null,\n                createElement('tr', null, createElement('td', null, 'Text')),\n              ),\n            ),\n          );\n        }\n\n        function B() {\n          return createElement(\n            'div',\n            null,\n            createElement(\n              'div',\n              null,\n              createElement(\n                'table',\n                null,\n                createElement('tr', null, createElement('td', null, 'bar')),\n              ),\n            ),\n          );\n        }\n\n        function C() {\n          return createElement(\n            'div',\n            null,\n            createElement(\n              'div',\n              null,\n              createElement(\n                'table',\n                null,\n                createElement('tr', null, createElement('td', null, 'text1')),\n              ),\n            ),\n          );\n        }\n\n        render(A(), container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>Text</td></tr></table></div></div>',\n        );\n\n        render(B(), container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>bar</td></tr></table></div></div>',\n        );\n\n        render(C(), container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text1</td></tr></table></div></div>',\n        );\n      });\n\n      it('variation 2', () => {\n        const A = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                null,\n                createElement('td', null, 'text', createElement('br', null)),\n              ),\n            ),\n          ),\n        );\n        const B = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement('tr', null, createElement('td', null, ['text'])),\n            ),\n          ),\n        );\n        const C = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                null,\n                createElement('td', null, ['value'], createElement('br', null)),\n              ),\n            ),\n          ),\n        );\n\n        render(A, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text<br></td></tr></table></div></div>',\n        );\n        render(B, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text</td></tr></table></div></div>',\n        );\n        render(C, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>value<br></td></tr></table></div></div>',\n        );\n      });\n\n      it('variation 3', () => {\n        const A = createElement(\n          'div',\n          null,\n          createElement('div', null, createElement('table', null)),\n        );\n        const B = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement('tr', null),\n              createElement(\n                'tr',\n                null,\n                createElement('td', null, 'A', createElement('br', null)),\n                createElement('td', null, 'B', createElement('br', null)),\n              ),\n              createElement('tr', null),\n            ),\n          ),\n        );\n        const C = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement('tr', null),\n              createElement(\n                'tr',\n                null,\n                createElement('td', null, createElement('br', null)),\n              ),\n            ),\n          ),\n        );\n\n        render(A, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table></table></div></div>',\n        );\n        render(B, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr></tr><tr><td>A<br></td><td>B<br></td></tr><tr></tr></table></div></div>',\n        );\n        render(C, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr></tr><tr><td><br></td></tr></table></div></div>',\n        );\n      });\n\n      it('variation 4', () => {\n        const A = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                null,\n                createElement('td', null, 'text 1', createElement('br', null)),\n              ),\n            ),\n          ),\n        );\n\n        const B = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                null,\n                createElement('td', null, createElement('br', null)),\n              ),\n            ),\n          ),\n        );\n\n        const C = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                null,\n                createElement('td', null, 'text 2', createElement('br', null)),\n              ),\n            ),\n          ),\n        );\n\n        render(A, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text 1<br></td></tr></table></div></div>',\n        );\n        render(B, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td><br></td></tr></table></div></div>',\n        );\n        render(C, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text 2<br></td></tr></table></div></div>',\n        );\n      });\n\n      it('variation 5', () => {\n        const A = [];\n\n        A[0] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            null,\n            createElement('td', null, createElement('br', null)),\n          ),\n        );\n        A[1] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            null,\n            createElement(\n              'td',\n              null,\n              'text 1',\n              'text a',\n              createElement('br', null),\n            ),\n          ),\n        );\n        A[2] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            null,\n            createElement('td', null, 'text 2', createElement('br', null)),\n          ),\n        );\n        A[3] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            null,\n            createElement(\n              'td',\n              null,\n              [createElement('br', null), 'text 3'],\n              createElement('br', null),\n            ),\n          ),\n        );\n        render(A[0], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td><br></td></tr></table>',\n        );\n        render(A[1], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td>text 1text a<br></td></tr></table>',\n        );\n        render(A[2], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td>text 2<br></td></tr></table>',\n        );\n        render(A[3], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td><br>text 3<br></td></tr></table>',\n        );\n      });\n\n      it('variation 6', () => {\n        const A = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                null,\n                createElement('td', null, 'text 1', createElement('br', null)),\n              ),\n            ),\n          ),\n        );\n\n        const B = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                null,\n                createElement('td', null, createElement('br', null)),\n              ),\n            ),\n          ),\n        );\n\n        const C = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                null,\n                createElement('td', null, 'text 2', createElement('br', null)),\n              ),\n            ),\n          ),\n        );\n\n        render(A, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text 1<br></td></tr></table></div></div>',\n        );\n        render(B, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td><br></td></tr></table></div></div>',\n        );\n        render(C, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text 2<br></td></tr></table></div></div>',\n        );\n      });\n\n      it('variation 7', () => {\n        const A = [];\n        A[0] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            null,\n            createElement('td', null, createElement('br', null)),\n          ),\n        );\n        A[1] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            null,\n            createElement('td', null, 'text 1', createElement('br', null)),\n          ),\n        );\n        A[2] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            null,\n            createElement('td', null, 'text 2', createElement('br', null)),\n          ),\n        );\n        A[3] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            null,\n            createElement(\n              'td',\n              null,\n              [createElement('br', null)],\n              'text 3',\n              createElement('br', null),\n            ),\n          ),\n        );\n\n        render(A[0], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td><br></td></tr></table>',\n        );\n        render(A[1], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td>text 1<br></td></tr></table>',\n        );\n        render(A[2], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td>text 2<br></td></tr></table>',\n        );\n        render(A[3], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td><br>text 3<br></td></tr></table>',\n        );\n      });\n    });\n\n    describe('KEYED updates', () => {\n      it('variation 1', () => {\n        function A() {\n          return createElement(\n            'div',\n            null,\n            createElement(\n              'div',\n              null,\n              createElement(\n                'table',\n                null,\n                createElement(\n                  'tr',\n                  { key: 'row1' },\n                  createElement('td', { key: 'td1' }, 'Text'),\n                ),\n              ),\n            ),\n          );\n        }\n\n        function B() {\n          return createElement(\n            'div',\n            null,\n            createElement(\n              'div',\n              null,\n              createElement(\n                'table',\n                null,\n                createElement(\n                  'tr',\n                  { key: 'row1' },\n                  createElement('td', { key: 'td1' }, 'bar'),\n                ),\n              ),\n            ),\n          );\n        }\n\n        function C() {\n          return createElement(\n            'div',\n            null,\n            createElement(\n              'div',\n              null,\n              createElement(\n                'table',\n                null,\n                createElement(\n                  'tr',\n                  { key: 'row1' },\n                  createElement('td', { key: 'td1' }, 'text1'),\n                ),\n              ),\n            ),\n          );\n        }\n\n        render(A(), container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>Text</td></tr></table></div></div>',\n        );\n\n        render(B(), container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>bar</td></tr></table></div></div>',\n        );\n\n        render(C(), container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text1</td></tr></table></div></div>',\n        );\n      });\n\n      it('variation 2', () => {\n        const A = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                { key: 'row1' },\n                createElement('td', { key: 'td1' }, [\n                  'text',\n                  createElement('br', null),\n                ]),\n              ),\n            ),\n          ),\n        );\n\n        const B = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                { key: 'row1' },\n                createElement('td', { key: 'td1' }, ['text']),\n              ),\n            ),\n          ),\n        );\n\n        const C = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                { key: 'row1' },\n                createElement('td', { key: 'td1' }, [\n                  'value',\n                  createElement('br', null),\n                ]),\n              ),\n            ),\n          ),\n        );\n\n        render(A, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text<br></td></tr></table></div></div>',\n        );\n        render(B, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text</td></tr></table></div></div>',\n        );\n        render(C, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>value<br></td></tr></table></div></div>',\n        );\n      });\n\n      it('variation 3', () => {\n        const A = createElement(\n          'div',\n          null,\n          createElement('div', null, createElement('table', null)),\n        );\n        const B = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement('tr', { key: 'row1' }),\n              createElement(\n                'tr',\n                { key: 'row2' },\n                createElement(\n                  'td',\n                  { key: 'td2-1' },\n                  'A',\n                  createElement('br', null),\n                ),\n                createElement(\n                  'td',\n                  { key: 'td2-2' },\n                  'B',\n                  createElement('br', null),\n                ),\n              ),\n              createElement('tr', { key: 'row3' }),\n            ),\n          ),\n        );\n        const C = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement('tr', { key: 'row1' }),\n              createElement(\n                'tr',\n                { key: 'row2' },\n                createElement(\n                  'td',\n                  { key: 'td2-2' },\n                  '',\n                  createElement('br', null),\n                ),\n              ),\n            ),\n          ),\n        );\n\n        render(A, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table></table></div></div>',\n        );\n        render(B, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr></tr><tr><td>A<br></td><td>B<br></td></tr><tr></tr></table></div></div>',\n        );\n        render(C, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr></tr><tr><td><br></td></tr></table></div></div>',\n        );\n      });\n\n      it('variation 4', () => {\n        const A = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                { key: 'row1' },\n                createElement(\n                  'td',\n                  { key: 'td1-1' },\n                  'text 1',\n                  createElement('br', null),\n                ),\n              ),\n            ),\n          ),\n        );\n\n        const B = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                { key: 'row1' },\n                createElement(\n                  'td',\n                  { key: 'td1-1' },\n                  '',\n                  createElement('br', null),\n                ),\n              ),\n            ),\n          ),\n        );\n\n        const C = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                { key: 'row1' },\n                createElement(\n                  'td',\n                  { key: 'td1-1' },\n                  'text 2',\n                  createElement('br', null),\n                ),\n              ),\n            ),\n          ),\n        );\n\n        render(A, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text 1<br></td></tr></table></div></div>',\n        );\n        render(B, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td><br></td></tr></table></div></div>',\n        );\n        render(C, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text 2<br></td></tr></table></div></div>',\n        );\n      });\n\n      it('variation 5', () => {\n        const A = [];\n\n        A[0] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            { key: 'row1' },\n            createElement(\n              'td',\n              { key: 'td1-1' },\n              '',\n              createElement('br', null),\n            ),\n          ),\n        );\n\n        A[1] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            { key: 'row1' },\n            createElement(\n              'td',\n              { key: 'td1-1' },\n              ['text 1', 'text a'],\n              createElement('br', null),\n            ),\n          ),\n        );\n\n        A[2] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            { key: 'row1' },\n            createElement(\n              'td',\n              { key: 'td1-1' },\n              ['text 2'],\n              createElement('br', null),\n            ),\n          ),\n        );\n\n        A[3] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            { key: 'row1' },\n            createElement(\n              'td',\n              { key: 'td1-1' },\n              [createElement('br', null), 'text 3'],\n              createElement('br', null),\n            ),\n          ),\n        );\n\n        render(A[0], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td><br></td></tr></table>',\n        );\n        render(A[1], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td>text 1text a<br></td></tr></table>',\n        );\n        render(A[2], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td>text 2<br></td></tr></table>',\n        );\n        render(A[3], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td><br>text 3<br></td></tr></table>',\n        );\n      });\n\n      it('variation 6', () => {\n        const A = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                { key: 'row1' },\n                createElement('td', { key: 'td1-1' }, [\n                  'text 1',\n                  createElement('br', null),\n                ]),\n              ),\n            ),\n          ),\n        );\n\n        const B = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                { key: 'row1' },\n                createElement('td', { key: 'td1-1' }, [\n                  '',\n                  createElement('br', null),\n                ]),\n              ),\n            ),\n          ),\n        );\n\n        const C = createElement(\n          'div',\n          null,\n          createElement(\n            'div',\n            null,\n            createElement(\n              'table',\n              null,\n              createElement(\n                'tr',\n                { key: 'row1' },\n                createElement('td', { key: 'td1-1' }, [\n                  'text 2',\n                  createElement('br', null),\n                ]),\n              ),\n            ),\n          ),\n        );\n\n        render(A, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text 1<br></td></tr></table></div></div>',\n        );\n        render(B, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td><br></td></tr></table></div></div>',\n        );\n        render(C, container);\n        expect(container.innerHTML).toBe(\n          '<div><div><table><tr><td>text 2<br></td></tr></table></div></div>',\n        );\n      });\n\n      it('variation 7', () => {\n        const A = [];\n\n        A[0] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            { key: 'row1' },\n            createElement(\n              'td',\n              { key: 'td1-1' },\n              '',\n              createElement('br', null),\n            ),\n          ),\n        );\n\n        A[1] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            { key: 'row1' },\n            createElement(\n              'td',\n              { key: 'td1-1' },\n              'text 1',\n              createElement('br', null),\n            ),\n          ),\n        );\n\n        A[2] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            { key: 'row1' },\n            createElement(\n              'td',\n              { key: 'td1-1' },\n              'text 2',\n              createElement('br', null),\n            ),\n          ),\n        );\n\n        A[3] = createElement(\n          'table',\n          null,\n          createElement(\n            'tr',\n            { key: 'row1' },\n            createElement(\n              'td',\n              { key: 'td1-1' },\n              [createElement('br', null), 'text 3'],\n              createElement('br', null),\n            ),\n          ),\n        );\n\n        render(A[0], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td><br></td></tr></table>',\n        );\n        render(A[1], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td>text 1<br></td></tr></table>',\n        );\n        render(A[2], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td>text 2<br></td></tr></table>',\n        );\n        render(A[3], container);\n        expect(container.innerHTML).toBe(\n          '<table><tr><td><br>text 3<br></td></tr></table>',\n        );\n      });\n    });\n  });\n\n  describe('Github #162', () => {\n    it('works', () => {\n      const A = [];\n\n      A[0] = createElement('div', null, 'text 1');\n      A[1] = createElement(\n        'div',\n        null,\n        'text 2',\n        createElement('br', null),\n        'text 3',\n      );\n      A[2] = createElement('div', null, 'text 4');\n\n      render(A[0], container);\n      expect(container.innerHTML).toBe('<div>text 1</div>');\n      render(A[1], container);\n      expect(container.innerHTML).toBe('<div>text 2<br>text 3</div>');\n      render(A[2], container);\n      expect(container.innerHTML).toBe('<div>text 4</div>');\n    });\n  });\n\n  describe('Github #162', () => {\n    it('works', () => {\n      const A = [];\n\n      A[0] = createElement('div', null, 'text 1', createElement('br', null));\n\n      A[1] = createElement('div', null, 'text 2');\n\n      A[2] = createElement('div', null, createElement('br', null), 'text 4');\n\n      render(A[0], container);\n      expect(container.innerHTML).toBe('<div>text 1<br></div>');\n      render(A[1], container);\n      expect(container.innerHTML).toBe('<div>text 2</div>');\n      render(A[2], container);\n      expect(container.innerHTML).toBe('<div><br>text 4</div>');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/__tests__/update.spec.jsx",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('Stateful Component updates', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should forget old updates', (done) => {\n    let updatesAfromOutside;\n\n    class A extends Component {\n      componentWillUnmount() {}\n\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          stuff: true,\n        };\n\n        updatesAfromOutside = this.updateMe.bind(this);\n      }\n\n      updateMe() {\n        this.setState({\n          stuff: false,\n        });\n      }\n\n      render() {\n        return <div>A Component A</div>;\n      }\n    }\n\n    class B extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return <div>B Component B</div>;\n      }\n    }\n\n    // Render A\n    const spy = spyOn(A.prototype, 'componentWillUnmount');\n    render(<A />, container);\n    expect(container.innerHTML).toBe('<div>A Component A</div>');\n    // Render B\n    render(<B />, container);\n    expect(container.innerHTML).toBe('<div>B Component B</div>');\n    expect(spy).toHaveBeenCalledTimes(1); // componentUnMount should have been called\n    spy.calls.reset();\n\n    // delayed update triggers for A\n    updatesAfromOutside();\n    expect(container.innerHTML).toBe('<div>B Component B</div>');\n\n    done();\n  });\n\n  it('Should give better error message when calling setState from constructor ??', () => {\n    // Following test simulates situation that setState is called when mounting process has not finished, fe. in constructor\n\n    class Parent extends Component {\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          show: false,\n        };\n\n        this.domagic = this.domagic.bind(this);\n\n        // Call setState\n        expect(() => {\n          this.setState({\n            show: true,\n          });\n        }).toThrow();\n      }\n\n      domagic() {\n        this.setState({\n          show: !this.state.show,\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            <button onclick={this.domagic} />\n            <Child show={this.state.show} />\n          </div>\n        );\n      }\n    }\n\n    class Child extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return (\n          <div>\n            {this.props.show ? (\n              <span className=\"hr red\">\n                <span className=\"hr-text\">Late</span>\n              </span>\n            ) : null}\n            <p>More content</p>\n          </div>\n        );\n      }\n    }\n\n    render(<Parent />, container);\n  });\n\n  it('Should update boolean properties when children change same time', () => {\n    let updateCaller = null;\n\n    class A extends Component {\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          values: [{ checked: false }, { checked: false }, { checked: false }],\n        };\n\n        this.updateCaller = this.updateCaller.bind(this);\n        updateCaller = this.updateCaller;\n      }\n\n      updateCaller() {\n        this.setState({\n          values: [{ checked: false }, { checked: false }],\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            {this.state.values.map(function (value) {\n              return <input type=\"checkbox\" checked={value.checked} />;\n            })}\n          </div>\n        );\n      }\n    }\n\n    render(<A />, container);\n    expect(container.innerHTML).toBe(\n      '<div><input type=\"checkbox\"><input type=\"checkbox\"><input type=\"checkbox\"></div>',\n    );\n    const firstChild = container.firstChild;\n    expect(firstChild.childNodes[0].checked).toBe(false);\n    expect(firstChild.childNodes[1].checked).toBe(false);\n    expect(firstChild.childNodes[2].checked).toBe(false);\n\n    const checkbox = container.querySelector('input');\n    checkbox.checked = true; // SIMULATE user selecting checkbox\n    expect(firstChild.childNodes[0].checked).toBe(true);\n\n    updateCaller(); // New render\n    expect(container.innerHTML).toBe(\n      '<div><input type=\"checkbox\"><input type=\"checkbox\"></div>',\n    );\n    expect(firstChild.childNodes[0].checked).toBe(false);\n    expect(firstChild.childNodes[1].checked).toBe(false);\n  });\n\n  it('Should Not get stuck in UNMOUNTED state', () => {\n    let updateCaller = null;\n\n    // This parent is used for setting up Test scenario, not much related\n    class Parent extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return (\n          <div>\n            <A />\n          </div>\n        );\n      }\n    }\n\n    // A component holds all the stuff together\n    class A extends Component {\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          obj: {\n            test: true,\n          },\n        };\n\n        this.updateCaller = this.updateCaller.bind(this);\n        updateCaller = this.updateCaller;\n      }\n\n      updateCaller() {\n        this.setState({\n          obj: {\n            test: !this.state.obj.test,\n          },\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            <B data={this.state.obj} />\n          </div>\n        );\n      }\n    }\n    // B has direct child C, B Is simple wrapper component\n    class B extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return <C data={this.props.data} />;\n      }\n    }\n\n    let stuckChild = null;\n\n    // C is real component which does the job\n    // C is the one that gets unmounted...\n    class C extends Component {\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          b: false,\n        };\n\n        this.imstuck = this.imstuck.bind(this);\n        stuckChild = this.imstuck;\n      }\n\n      imstuck() {\n        this.setState({\n          b: !this.state.b,\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            {this.props.data.test + ''}\n            {this.state.b + ''}\n          </div>\n        );\n      }\n    }\n\n    render(<Parent />, container);\n\n    expect(container.innerHTML).toBe(\n      '<div><div><div>truefalse</div></div></div>',\n    );\n\n    updateCaller();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>falsefalse</div></div></div>',\n    );\n    updateCaller();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>truefalse</div></div></div>',\n    );\n    updateCaller();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>falsefalse</div></div></div>',\n    );\n    stuckChild();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>falsetrue</div></div></div>',\n    );\n    stuckChild();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>falsefalse</div></div></div>',\n    );\n    stuckChild();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>falsetrue</div></div></div>',\n    );\n  });\n\n  it('Should Not get stuck in UNMOUNTED state - variation2', () => {\n    let updateCaller = null;\n\n    // This parent is used for setting up Test scenario, not much related\n    class Parent extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return (\n          <div>\n            <A />\n          </div>\n        );\n      }\n    }\n\n    // A component holds all the stuff together\n    class A extends Component {\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          obj: {\n            test: true,\n          },\n        };\n\n        this.updateCaller = this.updateCaller.bind(this);\n        updateCaller = this.updateCaller;\n      }\n\n      updateCaller() {\n        this.setState({\n          obj: {\n            test: !this.state.obj.test,\n          },\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            <B data={this.state.obj} />\n          </div>\n        );\n      }\n    }\n    // B has direct child C, B Is simple wrapper component\n    class B extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return <C data={this.props.data} />;\n      }\n    }\n\n    let stuckChild = null;\n\n    // C is real component which does the job\n    // C is the one that gets unmounted...\n    class C extends Component {\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          b: false,\n        };\n\n        this.imstuck = this.imstuck.bind(this);\n        stuckChild = this.imstuck;\n      }\n\n      imstuck() {\n        this.setState({\n          b: !this.state.b,\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            {this.props.data.test + ''}\n            {this.state.b + ''}\n          </div>\n        );\n      }\n    }\n\n    render(<Parent />, container);\n\n    expect(container.innerHTML).toBe(\n      '<div><div><div>truefalse</div></div></div>',\n    );\n\n    stuckChild();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>truetrue</div></div></div>',\n    );\n    stuckChild();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>truefalse</div></div></div>',\n    );\n    stuckChild();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>truetrue</div></div></div>',\n    );\n\n    updateCaller();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>falsetrue</div></div></div>',\n    );\n    updateCaller();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>truetrue</div></div></div>',\n    );\n    updateCaller();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>falsetrue</div></div></div>',\n    );\n\n    stuckChild();\n    expect(container.innerHTML).toBe(\n      '<div><div><div>falsefalse</div></div></div>',\n    );\n  });\n\n  it('Should keep order of nodes', () => {\n    let setItems = null;\n\n    class InnerComponentToGetUnmounted extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return (\n          <div className=\"common-root\">\n            {(() => {\n              if (this.props.i % 2 === 0) {\n                return (\n                  <div>\n                    DIV\n                    {this.props.value}\n                  </div>\n                );\n              } else {\n                return (\n                  <span>\n                    SPAN\n                    {this.props.value}\n                  </span>\n                );\n              }\n            })()}\n          </div>\n        );\n      }\n    }\n\n    const DropdownItem = ({ children }) => <li>{children}</li>;\n\n    class Looper extends Component {\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          items: [],\n        };\n\n        this.setItems = this.setItems.bind(this);\n\n        setItems = this.setItems;\n      }\n\n      setItems(collection) {\n        this.setState({\n          items: collection,\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            <ul>\n              {this.state.items.map(function (item, i) {\n                return (\n                  <DropdownItem key={item.value}>\n                    <InnerComponentToGetUnmounted\n                      key={0}\n                      i={i}\n                      value={item.value}\n                    />\n                    <span key={1}>{item.text}</span>\n                  </DropdownItem>\n                );\n              })}\n            </ul>\n          </div>\n        );\n      }\n    }\n\n    render(<Looper />, container);\n    expect(container.innerHTML).toBe('<div><ul></ul></div>');\n    setItems([\n      { value: 'val1', text: 'key1' },\n      { value: 'val2', text: 'key2' },\n      { value: 'val3', text: 'key3' },\n      { value: 'val4', text: 'key4' },\n    ]);\n\n    expect(container.innerHTML).toBe(\n      '<div><ul><li><div class=\"common-root\"><div>DIVval1</div></div><span>key1</span></li><li><div class=\"common-root\"><span>SPANval2</span></div><span>key2</span></li><li><div class=\"common-root\"><div>DIVval3</div></div><span>key3</span></li><li><div class=\"common-root\"><span>SPANval4</span></div><span>key4</span></li></ul></div>',\n    );\n\n    setItems([\n      { value: 'val2', text: 'key2' },\n      { value: 'val3', text: 'key3' },\n    ]);\n    expect(container.innerHTML).toBe(\n      '<div><ul><li><div class=\"common-root\"><div>DIVval2</div></div><span>key2</span></li><li><div class=\"common-root\"><span>SPANval3</span></div><span>key3</span></li></ul></div>',\n    );\n\n    setItems([\n      { value: 'val1', text: 'key1' },\n      { value: 'val2', text: 'key2' },\n      { value: 'val3', text: 'key3' },\n      { value: 'val4', text: 'key4' },\n    ]);\n    expect(container.innerHTML).toBe(\n      '<div><ul><li><div class=\"common-root\"><div>DIVval1</div></div><span>key1</span></li><li><div class=\"common-root\"><span>SPANval2</span></div><span>key2</span></li><li><div class=\"common-root\"><div>DIVval3</div></div><span>key3</span></li><li><div class=\"common-root\"><span>SPANval4</span></div><span>key4</span></li></ul></div>',\n    );\n  });\n\n  it('Should not crash when patching array to array with hooks', () => {\n    let updater = null;\n    const stuff = [<div>{['Test']}</div>, <span>1</span>];\n    const orig = [[<span ref={function () {}}>{'1'}</span>]];\n    class Stuff extends Component {\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          stuff,\n        };\n\n        updater = (_stuff) => {\n          this.setState({ stuff: _stuff });\n        };\n      }\n\n      render() {\n        return (\n          <div>\n            <div>{this.state.stuff}</div>\n          </div>\n        );\n      }\n    }\n\n    render(<Stuff />, container);\n    updater(orig);\n    expect(container.innerHTML).toBe('<div><div><span>1</span></div></div>');\n  });\n\n  it('Should allow camelCase properties when using JSX plugin', () => {\n    const fakeObj = {\n      func() {},\n    };\n    const submitSpy = spyOn(fakeObj, 'func');\n\n    class Tester extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return (\n          <form>\n            <input\n              id=\"inputId\"\n              onFocus={(e) => {\n                expect(e).toBeTruthy();\n              }}\n              type=\"text\"\n            />\n          </form>\n        );\n      }\n    }\n\n    render(<Tester />, container);\n    expect(container.innerHTML).toEqual(\n      '<form><input id=\"inputId\" type=\"text\"></form>',\n    );\n    const input = container.querySelector('#inputId');\n    expect(submitSpy).not.toHaveBeenCalled();\n    input.focus();\n  });\n\n  it('Should not append when replacing ES6 component with functional component', () => {\n    const A = function () {\n      return (\n        <div>\n          <div className=\"topheader\">\n            <h1>A</h1>\n          </div>\n        </div>\n      );\n    };\n\n    function B() {\n      return (\n        <div className=\"simplegrid\">\n          <div className=\"topheader\">\n            <h1>B</h1>\n          </div>\n          <div className=\"viewcontent fullscreen\">\n            <C />\n          </div>\n        </div>\n      );\n    }\n\n    class C extends Component {\n      componentWillUnmount() {}\n\n      render() {\n        return <div className=\"report-container\">C</div>;\n      }\n    }\n\n    const expectedA = '<div><div class=\"topheader\"><h1>A</h1></div></div>';\n    const expectedB =\n      '<div class=\"simplegrid\"><div class=\"topheader\"><h1>B</h1></div><div class=\"viewcontent fullscreen\"><div class=\"report-container\">C</div></div></div>';\n    render(<A />, container);\n    expect(container.innerHTML).toEqual(expectedA);\n\n    render(<B />, container);\n    expect(container.innerHTML).toEqual(expectedB);\n\n    // SO FAR SO GOOD\n\n    // NOW START SWAPPING\n\n    render(<A />, container);\n    expect(container.innerHTML).toEqual(expectedA);\n\n    render(<B />, container);\n    expect(container.innerHTML).toEqual(expectedB);\n\n    render(<A />, container);\n    expect(container.innerHTML).toEqual(expectedA);\n\n    render(<B />, container);\n    expect(container.innerHTML).toEqual(expectedB);\n\n    render(<A />, container);\n    expect(container.innerHTML).toEqual(expectedA);\n\n    render(<B />, container);\n    expect(container.innerHTML).toEqual(expectedB);\n\n    render(<A />, container);\n    expect(container.innerHTML).toEqual(expectedA);\n\n    render(<B />, container);\n    expect(container.innerHTML).toEqual(expectedB);\n  });\n\n  it('Should not fail removing child of component node Github #1111', () => {\n    const InfoLi = function InfoLi(props) {\n      return (\n        <li>\n          {createElement('input', {\n            checked: props.check,\n            type: props.type,\n            label: props.label,\n            onClick: props.onClick,\n          })}{' '}\n          {props.label}: check, then uncheck\n          <div>{props.children}</div>\n        </li>\n      );\n    };\n\n    class ConfigsList extends Component {\n      constructor(props) {\n        super(props);\n        this.state = {\n          checks: props.orderedConfigs.map((mod) => Boolean(mod.value)),\n        };\n      }\n\n      handleCheck(index, ifChecked) {\n        this.setState({\n          checks: this.state.checks.map((ch, i) =>\n            i === index ? ifChecked : ch,\n          ),\n        });\n      }\n\n      render(props) {\n        return (\n          <ol>\n            {props.orderedConfigs.map((conf, index) => {\n              const child =\n                this.state.checks[index] &&\n                createElement('div', null, 'hi there');\n              return (\n                <InfoLi\n                  label={conf}\n                  type=\"checkbox\"\n                  checked={this.state.checks[index]}\n                  onClick={(event) => {\n                    this.handleCheck(index, event.target.checked);\n                  }}\n                >\n                  {child}\n                </InfoLi>\n              );\n            })}\n          </ol>\n        );\n      }\n    }\n\n    render(<ConfigsList orderedConfigs={['use proxy?']} />, container);\n\n    const input = container.querySelector('input');\n\n    input.click();\n\n    input.click();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-create-element/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-create-element/package.json",
    "content": "{\n  \"name\": \"inferno-create-element\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Provides methods to create Inferno VNodes\",\n  \"author\": {\n    \"name\": \"Dominic Gannaway\",\n    \"email\": \"dg@domgan.com\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-create-element\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"files\": [\n    \"index.cjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"keywords\": [\n    \"babel\",\n    \"react\",\n    \"inferno\",\n    \"framework\",\n    \"interfaces\",\n    \"user interfaces\",\n    \"vdom\"\n  ],\n  \"dependencies\": {\n    \"inferno\": \"9.0.11\"\n  },\n  \"devDependencies\": {\n    \"inferno-shared\": \"9.0.11\",\n    \"inferno-vnode-flags\": \"9.0.11\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\",\n      \"inferno-vnode-flags\"\n    ],\n    \"moduleName\": \"Inferno\",\n    \"moduleGlobals\": {\n      \"inferno\": \"Inferno\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno-create-element/readme.md",
    "content": "# inferno-create-element\n\n> Inferno package with helpers to create Inferno elements\n\n## Install\n\n```\nnpm install inferno-create-element\n```\n\n## Usage\n\n```js\nimport { createElement } from 'inferno-create-element';\nimport { render } from 'inferno';\n\nrender(\n  createElement('div', { className: 'test' }, \"I'm a child!\"),\n  document.getElementById('app'),\n);\n```\n"
  },
  {
    "path": "packages/inferno-create-element/src/index.ts",
    "content": "import {\n  type Component,\n  createComponentVNode,\n  createFragment,\n  createVNode,\n  getFlagsForElementVnode,\n  type Inferno,\n  type Key,\n  type Props,\n  type Refs,\n  type VNode,\n} from 'inferno';\nimport {\n  isInvalid,\n  isNullOrUndef,\n  isString,\n  isUndefined,\n} from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\n\nexport function createElement<P>(\n  type:\n    | string\n    | Inferno.ComponentClass<P>\n    | Inferno.StatelessComponent<P & Refs<P>>\n    | typeof Component<P, any>,\n  props?: (P & Props<P>) | null,\n  ...children: any[]\n): VNode {\n  if (process.env.NODE_ENV !== 'production') {\n    if (isInvalid(type)) {\n      throw new Error(\n        'Inferno Error: createElement() name parameter cannot be undefined, null, false or true, It must be a string, class, function or forwardRef.',\n      );\n    }\n  }\n  let definedChildren: any;\n  let ref: any = null;\n  let key: Key = null;\n  let className: string | null = null;\n  let flags: VNodeFlags;\n  let newProps: Readonly<unknown> | null | undefined;\n  const childLen = children.length;\n\n  if (childLen === 1) {\n    definedChildren = children[0];\n  } else if (childLen > 1) {\n    definedChildren = [];\n\n    for (let i = 0; i < childLen; i++) {\n      definedChildren.push(children[i]);\n    }\n  }\n  if (isString(type)) {\n    flags = getFlagsForElementVnode(type);\n\n    if (!isNullOrUndef(props)) {\n      newProps = {};\n\n      for (const prop in props) {\n        if (prop === 'className' || prop === 'class') {\n          className = (props as any)[prop];\n        } else if (prop === 'key') {\n          key = props.key;\n        } else if (prop === 'children' && isUndefined(definedChildren)) {\n          definedChildren = props.children; // always favour children args over props\n        } else if (prop === 'ref') {\n          ref = props.ref;\n        } else {\n          if (prop === 'contenteditable') {\n            flags |= VNodeFlags.ContentEditable;\n          }\n          newProps[prop] = props[prop];\n        }\n      }\n    }\n  } else {\n    flags = VNodeFlags.ComponentUnknown;\n    if (!isUndefined(definedChildren)) {\n      if (!props) {\n        props = {} as P & Props<P>;\n      }\n      props.children = definedChildren;\n    }\n\n    if (!isNullOrUndef(props)) {\n      newProps = {};\n\n      for (const prop in props) {\n        if (prop === 'key') {\n          key = props.key;\n        } else if (prop === 'ref') {\n          ref = props.ref;\n        } else {\n          switch (prop) {\n            case 'onComponentDidAppear':\n            case 'onComponentDidMount':\n            case 'onComponentDidUpdate':\n            case 'onComponentShouldUpdate':\n            case 'onComponentWillDisappear':\n            case 'onComponentWillMount':\n            case 'onComponentWillUnmount':\n            case 'onComponentWillUpdate':\n              if (!ref) {\n                ref = {};\n              }\n              ref[prop] = props[prop];\n              break;\n            default:\n              newProps[prop] = props[prop];\n              break;\n          }\n        }\n      }\n    }\n\n    return createComponentVNode(flags, type, newProps, key, ref);\n  }\n\n  if (flags & VNodeFlags.Fragment) {\n    return createFragment(\n      childLen === 1 ? [definedChildren] : definedChildren,\n      ChildFlags.UnknownChildren,\n      key,\n    );\n  }\n\n  return createVNode(\n    flags,\n    type,\n    className,\n    definedChildren,\n    ChildFlags.UnknownChildren,\n    newProps,\n    key,\n    ref,\n  );\n}\n"
  },
  {
    "path": "packages/inferno-extras/README.md",
    "content": "# inferno-extras\n\nIs a collection of pure functions to ease some tasks with InfernoJS virtual DOM.\n\n## Install\n\n```\nnpm install inferno-extras\n```\n\n### isDOMInsideComponent\n\nDOM - Html node\n\ninstance - Class component instance\n\nReturns boolean:\n\n- `true` when DOM is found from children of given instance;\n- `false` when DOM node is not found.\n\n```js\nimport { isDOMInsideComponent } from 'inferno-extras';\n\nisDOMInsideComponent(DOM, instance);\n```\n\n**Motivation:**\n\nInfernoJS events bubble through the real DOM.\nThis can cause issues when you need to for example: stop event propagation from all child Components.\nNative `node.contains( otherNode )` returns false when Portal renders outside its root node.\nThis utility method solves the problem using non recursive DFS algorithm.\n\n**Example:**\n\n```jsx\nimport { Component } from 'inferno';\nimport { isDOMinsideVDOM } from 'inferno-extras';\n\nclass Clicker extends Component {\n\n  isClickOutside(event) {\n    // Check if click event came from any child component\n    if (!isDOMInsideComponent(event.target, this) {\n      this.setState({ closeMenu: true });\n    }\n  }\n\n...\n}\n```\n\n### isDOMInsideVNode\n\nExactly same as isDOMInsideComponent but second parameter is virtual node.\n"
  },
  {
    "path": "packages/inferno-extras/__tests__/extras.spec.jsx",
    "content": "import { Component, createPortal, render } from 'inferno';\nimport { isDOMInsideComponent, isDOMInsideVNode } from 'inferno-extras';\n\ndescribe('Extras', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('isDOMInsideComponent', () => {\n    it('Should return true if event.target is found outside Portal', () => {\n      const secondRoot = document.createElement('div');\n\n      let instance;\n\n      class Tester extends Component {\n        constructor(props) {\n          super(props);\n\n          instance = this;\n        }\n\n        render(props, state) {\n          return (\n            <div>\n              Move It\n              {createPortal(\n                <div>\n                  <span>test</span>\n                  <ul id=\"target\">\n                    <li />\n                  </ul>\n                </div>,\n                secondRoot,\n              )}\n            </div>\n          );\n        }\n      }\n\n      render(<Tester />, container);\n\n      expect(container.innerHTML).toBe('<div>Move It</div>');\n\n      const target = secondRoot.querySelector('#target');\n\n      expect(isDOMInsideComponent(target, instance)).toBe(true);\n\n      render(null, container);\n\n      expect(isDOMInsideComponent(target, instance)).toBe(false);\n    });\n\n    it('Should search through all different shapes of virtual nodes', () => {\n      const secondRoot = document.createElement('div');\n\n      let instance;\n\n      function Functional({ children }) {\n        return (\n          <div>\n            <span>{children}</span>\n          </div>\n        );\n      }\n\n      class Tester extends Component {\n        constructor(props) {\n          super(props);\n\n          instance = this;\n        }\n\n        render(props, state) {\n          return (\n            <div>\n              Move It\n              <div>\n                <div>\n                  <div />\n                  <div />\n                </div>\n              </div>\n              {createPortal(\n                <div>\n                  <span>\n                    <Functional>\n                      {[<div />, 'Okay', <span id=\"target\" />]}\n                    </Functional>\n                  </span>\n                  <ul>\n                    <li />\n                  </ul>\n                </div>,\n                secondRoot,\n              )}\n            </div>\n          );\n        }\n      }\n\n      render(<Tester />, container);\n\n      expect(container.innerHTML).toBe(\n        '<div>Move It<div><div><div></div><div></div></div></div></div>',\n      );\n\n      const target = secondRoot.querySelector('#target');\n\n      expect(isDOMInsideComponent(target, instance)).toBe(true);\n\n      render(null, container);\n\n      expect(isDOMInsideComponent(target, instance)).toBe(false);\n    });\n\n    it('Should return true if target node is the root', () => {\n      let instance;\n\n      class Tester extends Component {\n        constructor(props) {\n          super(props);\n\n          instance = this;\n        }\n\n        render() {\n          return (\n            <div id=\"target\">\n              <span />\n            </div>\n          );\n        }\n      }\n\n      render(<Tester />, container);\n\n      const target = container.querySelector('#target');\n\n      expect(isDOMInsideComponent(target, instance)).toBe(true);\n    });\n\n    it('Should return false if target is not found', () => {\n      const instances = [];\n\n      class Tester extends Component {\n        constructor(props) {\n          super(props);\n\n          instances.push(this);\n        }\n\n        render() {\n          return (\n            <div id={this.props.id}>\n              <span />\n            </div>\n          );\n        }\n      }\n\n      render(\n        <div>\n          <Tester />\n          <Tester id=\"target\" />\n          <Tester />\n        </div>,\n        container,\n      );\n\n      const target = container.querySelector('#target');\n\n      expect(isDOMInsideComponent(target, instances[0])).toBe(false);\n      expect(isDOMInsideComponent(target, instances[1])).toBe(true);\n      expect(isDOMInsideComponent(target, instances[2])).toBe(false);\n    });\n\n    it('Should return false if target is detached', () => {\n      const instances = [];\n\n      class Tester extends Component {\n        constructor(props) {\n          super(props);\n\n          instances.push(this);\n        }\n\n        render() {\n          return (\n            <div id={this.props.id}>\n              <span />\n            </div>\n          );\n        }\n      }\n\n      render(\n        <div>\n          <Tester key=\"1\" />\n          <Tester key=\"2\" id=\"target\" />\n          <Tester key=\"3\" />\n        </div>,\n        container,\n      );\n\n      const target = container.querySelector('#target');\n\n      expect(isDOMInsideComponent(target, instances[0])).toBe(false);\n      expect(isDOMInsideComponent(target, instances[1])).toBe(true);\n      expect(isDOMInsideComponent(target, instances[2])).toBe(false);\n\n      render(\n        <div>\n          <Tester key=\"1\" />\n          <Tester key=\"change-it\" id=\"target\" />\n          <Tester key=\"3\" />\n        </div>,\n        container,\n      );\n\n      expect(isDOMInsideComponent(target, instances[0])).toBe(false);\n      expect(isDOMInsideComponent(target, instances[1])).toBe(false);\n      expect(isDOMInsideComponent(target, instances[2])).toBe(false);\n    });\n  });\n\n  describe('isDOMInsideVNode', () => {\n    it('Should work same way but for vNode', () => {\n      const vNode = (\n        <div>\n          <div id=\"target\">Ok</div>\n        </div>\n      );\n\n      render(\n        <div>\n          <span>Test</span>\n          {vNode}\n        </div>,\n        container,\n      );\n\n      expect(isDOMInsideVNode(container.querySelector('#target'), vNode)).toBe(\n        true,\n      );\n    });\n\n    it('Should return true if that is the ndoe', () => {\n      const vNode = <div id=\"target\">Ok</div>;\n\n      render(\n        <div>\n          <span>Test</span>\n          {vNode}\n        </div>,\n        container,\n      );\n\n      expect(isDOMInsideVNode(container.querySelector('#target'), vNode)).toBe(\n        true,\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-extras/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-extras/package.json",
    "content": "{\n  \"name\": \"inferno-extras\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Collection of utilities for InfernoJS\",\n  \"author\": {\n    \"name\": \"Sampo Kivistö<Havunen>\",\n    \"email\": \"sampo.kivisto@live.fi\",\n    \"url\": \"https://github.com/havunen\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"keywords\": [\n    \"inferno\",\n    \"performance\",\n    \"extras\",\n    \"methods\",\n    \"utils\"\n  ],\n  \"rollup\": {\n    \"moduleName\": \"Inferno\"\n  },\n  \"files\": [\n    \"index.cjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-extras\"\n  },\n  \"dependencies\": {\n    \"inferno\": \"9.0.11\"\n  },\n  \"devDependencies\": {\n    \"inferno-vnode-flags\": \"9.0.11\"\n  }\n}\n"
  },
  {
    "path": "packages/inferno-extras/src/findDOMNode.ts",
    "content": "import { type Component, findDOMFromVNode, type VNode } from 'inferno';\n\nexport function findDOMNode(ref: VNode | Component | Node): Node | null {\n  if (ref && (ref as Node).nodeType) {\n    return ref as Node;\n  }\n\n  if (!ref || (ref as Component).$UN) {\n    return null;\n  }\n\n  if ((ref as Component).$LI) {\n    return findDOMFromVNode((ref as Component).$LI, true);\n  }\n\n  if ((ref as VNode).flags) {\n    return findDOMFromVNode(ref as VNode, true);\n  }\n\n  return null;\n}\n"
  },
  {
    "path": "packages/inferno-extras/src/index.ts",
    "content": "import { isDOMInsideComponent, isDOMInsideVNode } from './isDOMInsideVDOM';\nimport { findDOMNode } from './findDOMNode';\n\nexport { findDOMNode, isDOMInsideVNode, isDOMInsideComponent };\n"
  },
  {
    "path": "packages/inferno-extras/src/isDOMInsideVDOM.ts",
    "content": "import type { Component, VNode } from 'inferno';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\n\nexport function isDOMInsideVNode(DOM: Element, vNode: VNode): boolean {\n  const stack = [vNode];\n  let _vNode;\n  let flags;\n  let children;\n\n  while (stack.length > 0) {\n    _vNode = stack.pop();\n\n    if (_vNode.dom === DOM) {\n      return true;\n    }\n\n    flags = _vNode.flags;\n    children = _vNode.children;\n\n    if (flags & VNodeFlags.ComponentClass) {\n      stack.push(children.$LI);\n    } else if (flags & VNodeFlags.ComponentFunction) {\n      stack.push(children);\n    } else {\n      flags = _vNode.childFlags;\n\n      if (flags & ChildFlags.MultipleChildren) {\n        let i = children.length;\n\n        while (i--) {\n          stack.push(children[i]);\n        }\n      } else if (flags & ChildFlags.HasVNodeChildren) {\n        stack.push(children);\n      }\n    }\n  }\n\n  return false;\n}\n\nexport function isDOMInsideComponent(\n  DOM: Element,\n  instance: Component<any, any>,\n): boolean {\n  if (instance.$UN) {\n    return false;\n  }\n\n  return isDOMInsideVNode(DOM, instance.$LI);\n}\n"
  },
  {
    "path": "packages/inferno-hydrate/__tests__/hydrate-forward-ref.spec.tsx",
    "content": "import { Component, createRef, forwardRef, RefObject, render } from 'inferno';\nimport { hydrate } from 'inferno-hydrate';\n\ndescribe('Hydrate - Forward Ref', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should be possible to forward createRef', () => {\n    const FancyButton = forwardRef((props, ref) => (\n      <button ref={ref} className=\"FancyButton\">\n        {props.children}\n      </button>\n    ));\n\n    expect(FancyButton.render).toBeDefined();\n\n    class Hello extends Component {\n      private readonly btn: RefObject<Element>;\n\n      constructor(props) {\n        super(props);\n\n        // You can now get a ref directly to the DOM button:\n        this.btn = createRef();\n      }\n\n      componentDidMount() {\n        expect(this.btn.current).toBe(container.querySelector('button'));\n      }\n\n      render() {\n        return <FancyButton ref={this.btn}>Click me!</FancyButton>;\n      }\n    }\n\n    container.innerHTML = '<button class=\"FancyButton\">Click me!</button>';\n\n    hydrate(<Hello />, container);\n\n    expect(container.innerHTML).toBe(\n      '<button class=\"FancyButton\">Click me!</button>',\n    );\n  });\n\n  it('Should be possible to forward callback ref', () => {\n    const FancyButton = forwardRef((props, ref) => (\n      <button ref={ref} className=\"FancyButton\">\n        {props.children}\n      </button>\n    ));\n\n    expect(FancyButton.render).toBeDefined();\n\n    class Hello extends Component {\n      render() {\n        return (\n          <FancyButton\n            ref={(btn) => {\n              if (btn) {\n                expect(btn).toBe(container.querySelector('button'));\n              }\n            }}\n          >\n            Click me!\n          </FancyButton>\n        );\n      }\n    }\n\n    container.innerHTML = '<button class=\"FancyButton\">Click me!</button>';\n\n    hydrate(<Hello />, container);\n\n    expect(container.innerHTML).toBe(\n      '<button class=\"FancyButton\">Click me!</button>',\n    );\n\n    render(null, container);\n\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('Should be possible to patch forwardRef component', () => {\n    const FancyButton = forwardRef((props, ref) => {\n      return (\n        <button ref={ref} className=\"FancyButton\">\n          {props.children}\n        </button>\n      );\n    });\n\n    expect(FancyButton.render).toBeDefined();\n\n    let firstVal = null;\n\n    container.innerHTML = '<button class=\"FancyButton\">Click me!</button>';\n\n    hydrate(\n      <FancyButton\n        ref={(btn) => {\n          firstVal = btn;\n        }}\n      >\n        Click me!\n      </FancyButton>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<button class=\"FancyButton\">Click me!</button>',\n    );\n    expect(firstVal).not.toBe(null);\n\n    let secondVal = null;\n\n    render(\n      <FancyButton\n        ref={(btn) => {\n          secondVal = btn;\n        }}\n      >\n        Click me! 222\n      </FancyButton>,\n      container,\n    );\n\n    expect(firstVal).toBe(null);\n    expect(secondVal).not.toBe(null);\n\n    expect(container.innerHTML).toBe(\n      '<button class=\"FancyButton\">Click me! 222</button>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-hydrate/__tests__/hydrate.spec.tsx",
    "content": "import {\n  Component,\n  createFragment,\n  createPortal,\n  createRef,\n  Fragment,\n  InfernoNode,\n  render,\n  rerender,\n} from 'inferno';\nimport { hydrate } from 'inferno-hydrate';\nimport { h } from 'inferno-hyperscript';\nimport { triggerEvent } from 'inferno-utils';\nimport { ChildFlags } from 'inferno-vnode-flags';\nimport { createElement } from 'inferno-create-element';\n\ndescribe('rendering routine', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('hydrate', () => {\n    it('Should be possible to hydrate manually', () => {\n      // create matching DOM\n      container.innerHTML = '<input type=\"checkbox\"/>';\n\n      let clickChecked: boolean | null = null;\n      let changeChecked: boolean | null = null;\n\n      // Hydrate manually, instead rendering\n      hydrate(\n        <input\n          type=\"checkbox\"\n          checked={false}\n          onClick={(e) => {\n            clickChecked = e.target.checked;\n          }}\n          onChange={(e) => {\n            changeChecked = e.target.checked;\n          }}\n        />,\n        container,\n      );\n      const input = container.firstChild;\n\n      triggerEvent('click', input);\n\n      expect(input.checked).toBe(false);\n      expect(clickChecked).toBe(true);\n      expect(changeChecked).toBe(true);\n    });\n\n    it('Should Manually hydrating should also attach root and patch when rendering next time', () => {\n      // create matching DOM\n      const spy = jasmine.createSpy('spy');\n      container.innerHTML = '<div><input type=\"checkbox\"/></div>';\n\n      let clickChecked: boolean | null = null;\n      let changeChecked: boolean | null = null;\n\n      // Hydrate manually, instead rendering\n      hydrate(\n        <div ref={spy}>\n          <input\n            type=\"checkbox\"\n            checked={false}\n            onClick={(e) => {\n              clickChecked = e.target.checked;\n            }}\n            onChange={(e) => {\n              changeChecked = e.target.checked;\n            }}\n          />\n        </div>,\n        container,\n      );\n\n      const oldInput = container.firstChild.firstChild;\n\n      expect(spy.calls.count()).toBe(1);\n\n      render(\n        <div ref={spy}>\n          <input\n            type=\"checkbox\"\n            checked={true}\n            className=\"new-class\"\n            onClick={(e) => {\n              clickChecked = e.target.checked;\n            }}\n            onChange={(e) => {\n              changeChecked = e.target.checked;\n            }}\n          />\n        </div>,\n        container,\n      );\n\n      expect(spy.calls.count()).toBe(1);\n\n      const input = container.querySelector('input.new-class');\n\n      expect(oldInput).toBe(input); // It should still be the same DOM node\n\n      triggerEvent('click', input);\n\n      expect(input.checked).toBe(true);\n      expect(clickChecked).toBe(false);\n      expect(changeChecked).toBe(false);\n\n      render(null, container);\n\n      expect(spy.calls.count()).toBe(2);\n    });\n\n    it('Should change value and defaultValue to empty when hydrating over existing textArea', () => {\n      container.innerHTML = '<textarea>foobar</textarea>';\n\n      hydrate(<textarea />, container);\n      expect(container.firstChild.value).toBe('');\n      expect(container.firstChild.defaultValue).toBe('');\n    });\n\n    it('Should work with object ref on element vNode', () => {\n      // create matching DOM\n      container.innerHTML = '<div>Okay<span>foobar</span></div>';\n\n      const newRef = createRef<HTMLSpanElement>();\n\n      hydrate(\n        <div>\n          Okay\n          <span ref={newRef}>Foobar</span>\n        </div>,\n        container,\n      );\n\n      expect(newRef.current).toBe(container.querySelector('span'));\n      expect(container.innerHTML).toBe('<div>Okay<span>Foobar</span></div>');\n    });\n\n    it('Should work with object ref on component vNode', () => {\n      // create matching DOM\n      container.innerHTML = '<div>Okay<span>foobar</span></div>';\n\n      let instance: Foobar | null = null;\n\n      class Foobar extends Component {\n        constructor(props, context) {\n          super(props, context);\n\n          instance = this;\n        }\n\n        render() {\n          return (\n            <Fragment>\n              <span>1</span>\n              {this.props.children}\n              <span>2</span>\n            </Fragment>\n          );\n        }\n      }\n\n      const newRef = createRef<Foobar>();\n\n      hydrate(\n        <div>\n          Okay\n          <Foobar ref={newRef}>Foobar</Foobar>\n        </div>,\n        container,\n      );\n\n      expect(newRef.current).toBe(instance);\n      expect(container.innerHTML).toBe(\n        '<div>Okay<span>1</span>Foobar<span>2</span></div>',\n      );\n    });\n  });\n\n  describe('Hydrate fragments', () => {\n    function runAllTests() {\n      it('Should hydrate and unmount fragment', () => {\n        class Example extends Component {\n          render() {\n            return createFragment(\n              [<div>First</div>, <div>second</div>],\n              ChildFlags.HasNonKeyedChildren,\n            );\n          }\n        }\n\n        hydrate(<Example />, container);\n\n        expect(container.innerHTML).toBe('<div>First</div><div>second</div>');\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should hydrate nested fragment', () => {\n        class Example extends Component {\n          render() {\n            return createFragment(\n              [\n                <div>First</div>,\n                createFragment(\n                  [<div>Sub1</div>, <div>Sub2</div>],\n                  ChildFlags.HasNonKeyedChildren,\n                ),\n                <div>second</div>,\n              ],\n              ChildFlags.HasNonKeyedChildren,\n            );\n          }\n        }\n\n        hydrate(<Example />, container);\n\n        expect(container.innerHTML).toBe(\n          '<div>First</div><div>Sub1</div><div>Sub2</div><div>second</div>',\n        );\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should be to replace component with fragment with another component', () => {\n        class Example extends Component {\n          render() {\n            return createFragment(\n              [\n                <div>First</div>,\n                createFragment(\n                  [<div>Sub1</div>, <div>Sub2</div>],\n                  ChildFlags.HasNonKeyedChildren,\n                ),\n                <div>second</div>,\n              ],\n              ChildFlags.HasNonKeyedChildren,\n            );\n          }\n        }\n\n        function FunctionalComp() {\n          return createFragment(\n            [<div>Functional</div>],\n            ChildFlags.HasNonKeyedChildren,\n          );\n        }\n\n        hydrate(<Example />, container);\n\n        expect(container.innerHTML).toBe(\n          '<div>First</div><div>Sub1</div><div>Sub2</div><div>second</div>',\n        );\n\n        render(<FunctionalComp />, container);\n\n        expect(container.innerHTML).toBe('<div>Functional</div>');\n\n        render(<Example />, container);\n\n        expect(container.innerHTML).toBe(\n          '<div>First</div><div>Sub1</div><div>Sub2</div><div>second</div>',\n        );\n\n        render(<FunctionalComp />, container);\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should be possible to move fragments', () => {\n        const fragmentA = () =>\n          createFragment(\n            [<div id=\"a1\">A1</div>, <div>A2</div>],\n            ChildFlags.HasNonKeyedChildren,\n            'A',\n          );\n\n        const fragmentB = () =>\n          createFragment(\n            [<div id=\"b1\">B1</div>],\n            ChildFlags.HasNonKeyedChildren,\n            'B',\n          );\n\n        const fragmentC = () =>\n          createFragment(\n            [<div id=\"c1\">C1</div>, <div>C2</div>, <div>C3</div>],\n            ChildFlags.HasNonKeyedChildren,\n            'C',\n          );\n\n        hydrate(\n          <div>\n            {fragmentA()}\n            {fragmentB()}\n            {fragmentC()}\n          </div>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div><div id=\"a1\">A1</div><div>A2</div><div id=\"b1\">B1</div><div id=\"c1\">C1</div><div>C2</div><div>C3</div></div>',\n        );\n\n        const A1 = container.querySelector('#a1');\n        const B1 = container.querySelector('#b1');\n        const C1 = container.querySelector('#c1');\n\n        // Switch order\n        render(\n          <div>\n            {fragmentC()}\n            {fragmentA()}\n            {fragmentB()}\n          </div>,\n          container,\n        );\n\n        // Verify dom has changed and nodes are the same\n        expect(container.innerHTML).toBe(\n          '<div><div id=\"c1\">C1</div><div>C2</div><div>C3</div><div id=\"a1\">A1</div><div>A2</div><div id=\"b1\">B1</div></div>',\n        );\n\n        expect(container.querySelector('#a1')).toBe(A1);\n        expect(container.querySelector('#b1')).toBe(B1);\n        expect(container.querySelector('#c1')).toBe(C1);\n\n        // Switch order again\n        render(\n          <div>\n            {fragmentB()}\n            {fragmentC()}\n          </div>,\n          container,\n        );\n\n        // Verify dom has changed and nodes are the same\n        expect(container.innerHTML).toBe(\n          '<div><div id=\"b1\">B1</div><div id=\"c1\">C1</div><div>C2</div><div>C3</div></div>',\n        );\n\n        expect(container.querySelector('#a1')).toBe(null);\n        expect(container.querySelector('#b1')).toBe(B1);\n        expect(container.querySelector('#c1')).toBe(C1);\n      });\n\n      it('Should clone fragment children if they are passed as reference', () => {\n        const fragmentA = createFragment(\n          [<div id=\"a1\">A1</div>, <div>A2</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'A',\n        );\n        const fragmentB = createFragment(\n          [<div id=\"b1\">B1</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'B',\n        );\n        const fragmentC = createFragment(\n          [<div id=\"c1\">C1</div>, <div>C2</div>, <div>C3</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'C',\n        );\n\n        const content = [fragmentC];\n\n        function SFC() {\n          return (\n            <Fragment>\n              <span>1</span>\n              <Fragment>{content}</Fragment>\n              <span>2</span>\n            </Fragment>\n          );\n        }\n\n        hydrate(\n          <Fragment>\n            {fragmentA}\n            <SFC key=\"sfc\" />\n            {fragmentB}\n            {fragmentC}\n          </Fragment>,\n          container,\n        );\n\n        const FragmentAHtml = '<div id=\"a1\">A1</div><div>A2</div>';\n        const FragmentBHtml = '<div id=\"b1\">B1</div>';\n        const FragmentCHtml = '<div id=\"c1\">C1</div><div>C2</div><div>C3</div>';\n        const SFCHtml = '<span>1</span>' + FragmentCHtml + '<span>2</span>';\n\n        expect(container.innerHTML).toBe(\n          FragmentAHtml + SFCHtml + FragmentBHtml + FragmentCHtml,\n        );\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should be possible to move component with fragment root', () => {\n        const fragmentA = createFragment(\n          [<div id=\"a1\">A1</div>, <div>A2</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'A',\n        );\n        const fragmentB = createFragment(\n          [<div id=\"b1\">B1</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'B',\n        );\n        const fragmentC = createFragment(\n          [<div id=\"c1\">C1</div>, <div>C2</div>, <div>C3</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'C',\n        );\n\n        const content = [fragmentC];\n\n        function SFC() {\n          return (\n            <Fragment>\n              <span>1</span>\n              <Fragment>{content}</Fragment>\n              <span>2</span>\n            </Fragment>\n          );\n        }\n\n        hydrate(\n          <Fragment>\n            {fragmentA}\n            <SFC key=\"sfc\" />\n            {fragmentB}\n            {fragmentC}\n          </Fragment>,\n          container,\n        );\n\n        const FragmentAHtml = '<div id=\"a1\">A1</div><div>A2</div>';\n        const FragmentBHtml = '<div id=\"b1\">B1</div>';\n        const FragmentCHtml = '<div id=\"c1\">C1</div><div>C2</div><div>C3</div>';\n        const SFCHtml = '<span>1</span>' + FragmentCHtml + '<span>2</span>';\n\n        expect(container.innerHTML).toBe(\n          FragmentAHtml + SFCHtml + FragmentBHtml + FragmentCHtml,\n        );\n\n        // Switch order\n        render(\n          <Fragment>\n            {fragmentA}\n            {fragmentC}\n            <SFC key=\"sfc\" />\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          FragmentAHtml + FragmentCHtml + SFCHtml,\n        );\n\n        // Switch order again\n        render(\n          <Fragment>\n            <div key=\"1\">1</div>\n            <SFC key=\"sfc\" />\n            {fragmentA}\n            {fragmentC}\n            <div key=\"1\">2</div>\n          </Fragment>,\n          container,\n        );\n\n        // Verify dom has changed and nodes are the same\n        expect(container.innerHTML).toBe(\n          '<div>1</div>' +\n            SFCHtml +\n            FragmentAHtml +\n            FragmentCHtml +\n            '<div>2</div>',\n        );\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should be possible to move component with fragment root #2', () => {\n        const fragmentA = createFragment(\n          [<div id=\"a1\">A1</div>, <div>A2</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'A',\n        );\n        const fragmentB = createFragment(\n          [<div id=\"b1\">B1</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'B',\n        );\n        const fragmentC = createFragment(\n          [<div id=\"c1\">C1</div>, <div>C2</div>, <div>C3</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'C',\n        );\n\n        const content = [fragmentC];\n\n        function SFC() {\n          return (\n            <Fragment>\n              <span>1</span>\n              <Fragment>{content}</Fragment>\n              <span>2</span>\n            </Fragment>\n          );\n        }\n\n        hydrate(\n          <Fragment>\n            {fragmentA}\n            <SFC key=\"sfc1\" />\n            {fragmentB}\n            <SFC key=\"sfc2\" />\n            {fragmentC}\n            <SFC key=\"sfc3\" />\n          </Fragment>,\n          container,\n        );\n\n        const FragmentAHtml = '<div id=\"a1\">A1</div><div>A2</div>';\n        const FragmentBHtml = '<div id=\"b1\">B1</div>';\n        const FragmentCHtml = '<div id=\"c1\">C1</div><div>C2</div><div>C3</div>';\n        const SFCHtml = '<span>1</span>' + FragmentCHtml + '<span>2</span>';\n\n        expect(container.innerHTML).toBe(\n          FragmentAHtml +\n            SFCHtml +\n            FragmentBHtml +\n            SFCHtml +\n            FragmentCHtml +\n            SFCHtml,\n        );\n\n        // Switch order\n        render(\n          <Fragment>\n            <SFC key=\"sfc3\" />\n            {fragmentA}\n            <SFC key=\"sfc1\" />\n            {fragmentC}\n            <SFC key=\"sfc2\" />\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          SFCHtml + FragmentAHtml + SFCHtml + FragmentCHtml + SFCHtml,\n        );\n\n        // Switch order again\n        render(\n          <Fragment>\n            <div key=\"1\">1</div>\n            <SFC key=\"sfc1\" />\n            <SFC key=\"sfc2\" />\n            {fragmentA}\n            {fragmentC}\n            <div key=\"1\">2</div>\n            <SFC key=\"sfc3\" />\n          </Fragment>,\n          container,\n        );\n\n        // Verify dom has changed and nodes are the same\n        expect(container.innerHTML).toBe(\n          '<div>1</div>' +\n            SFCHtml +\n            SFCHtml +\n            FragmentAHtml +\n            FragmentCHtml +\n            '<div>2</div>' +\n            SFCHtml,\n        );\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should be possible to hydrate fragments JSX way', () => {\n        interface FragmenterProps {\n          first: string;\n          mid: string;\n          last: string;\n          changeOrder?: boolean;\n        }\n        function Fragmenter({\n          first,\n          mid,\n          last,\n          changeOrder,\n        }: FragmenterProps) {\n          if (changeOrder) {\n            return (\n              <>\n                <div>{first}</div>\n                <>\n                  More\n                  {null}\n                  Hey!\n                  <Fragment>\n                    <>Large {last}</>\n                    <Fragment>And Small</Fragment>\n                  </Fragment>\n                  <>Nesting</>\n                  {mid}\n                </>\n                <span>bar</span>\n                {null}\n              </>\n            );\n          }\n          return (\n            <>\n              <div>{first}</div>\n              Hey!\n              <>\n                More\n                <>Nesting</>\n                {mid}\n                <Fragment>\n                  <>Large {last}</>\n                  <Fragment>And Small</Fragment>\n                </Fragment>\n              </>\n              <span>bar</span>\n            </>\n          );\n        }\n\n        let mountCounter = 0;\n        let unmountCounter = 0;\n\n        class FoobarCom extends Component<{ node: HTMLDivElement }> {\n          componentWillMount() {\n            mountCounter++;\n          }\n\n          componentWillUnmount() {\n            unmountCounter++;\n          }\n\n          render(props) {\n            return (\n              <>\n                {props.children}\n                {createPortal(<div>InvisiblePortalCreator</div>, props.node)}\n                {null}\n                Try out some crazy stuff\n              </>\n            );\n          }\n        }\n\n        const portalNode = document.createElement('div');\n\n        hydrate(\n          <FoobarCom node={portalNode}>\n            <Fragmenter first=\"first\" mid=\"MID\" last={<div>Why?</div>} />\n          </FoobarCom>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div>first</div>Hey!MoreNestingMIDLarge <div>Why?</div>And Small<span>bar</span>Try out some crazy stuff',\n        );\n        expect(portalNode.innerHTML).toBe('<div>InvisiblePortalCreator</div>');\n\n        render(\n          <FoobarCom node={portalNode}>\n            <Fragmenter\n              first={<span>GoGo</span>}\n              mid=\"MID\"\n              last={<div>Why?</div>}\n              changeOrder={true}\n            />\n          </FoobarCom>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div><span>GoGo</span></div>MoreHey!Large <div>Why?</div>And SmallNestingMID<span>bar</span>Try out some crazy stuff',\n        );\n        expect(portalNode.innerHTML).toBe('<div>InvisiblePortalCreator</div>');\n\n        render(\n          <FoobarCom node={portalNode}>\n            <Fragmenter first=\"first\" mid=\"MID\" last={<div>Why?</div>} />\n          </FoobarCom>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div>first</div>Hey!MoreNestingMIDLarge <div>Why?</div>And Small<span>bar</span>Try out some crazy stuff',\n        );\n        expect(portalNode.innerHTML).toBe('<div>InvisiblePortalCreator</div>');\n      });\n\n      it('Should hydrate deeply nested fragment', () => {\n        function Fragmenter2() {\n          return (\n            <>\n              <>\n                <>\n                  <>\n                    <>\n                      <>\n                        <>\n                          <>Okay!</>\n                        </>\n                      </>\n                    </>\n                  </>\n                </>\n              </>\n            </>\n          );\n        }\n\n        hydrate(<Fragmenter2 />, container);\n\n        expect(container.innerHTML).toBe('Okay!');\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should append DOM nodes to correct position when component root Fragmnet change', () => {\n        class TestRoot extends Component {\n          render() {\n            return <>{this.props.children}</>;\n          }\n        }\n\n        hydrate(\n          <div>\n            <TestRoot>\n              <div>1</div>\n              <div>2</div>\n            </TestRoot>\n            <TestRoot>\n              <span>Ok</span>\n              <span>Test</span>\n            </TestRoot>\n          </div>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div><div>1</div><div>2</div><span>Ok</span><span>Test</span></div>',\n        );\n\n        render(\n          <div>\n            <TestRoot>\n              <div>1</div>\n              <div>2</div>\n              <div>3</div>\n              <div>4</div>\n            </TestRoot>\n            <TestRoot>\n              <div>Other</div>\n            </TestRoot>\n          </div>,\n          container,\n        );\n        expect(container.innerHTML).toBe(\n          '<div><div>1</div><div>2</div><div>3</div><div>4</div><div>Other</div></div>',\n        );\n      });\n\n      it('Should not clear whole parent element when fragment children are cleared', () => {\n        class TestRoot extends Component {\n          render() {\n            return <>{this.props.children}</>;\n          }\n        }\n\n        hydrate(\n          <div>\n            <TestRoot>\n              <div>1</div>\n              <div>2</div>\n            </TestRoot>\n            <TestRoot>\n              <span>Ok</span>\n              <span>Test</span>\n            </TestRoot>\n          </div>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<div><div>1</div><div>2</div><span>Ok</span><span>Test</span></div>',\n        );\n\n        render(\n          <div>\n            <TestRoot>\n              <div>1</div>\n              <div>2</div>\n              <div>3</div>\n              <div>4</div>\n            </TestRoot>\n            <TestRoot />\n          </div>,\n          container,\n        );\n        expect(container.innerHTML).toBe(\n          '<div><div>1</div><div>2</div><div>3</div><div>4</div></div>',\n        );\n      });\n\n      it('Should move fragment and all its contents when using Fragment long syntax with keys', () => {\n        let unmountCounter = 0;\n        let mountCounter = 0;\n\n        class TestLifecycle extends Component {\n          componentWillUnmount() {\n            unmountCounter++;\n          }\n\n          componentWillMount() {\n            mountCounter++;\n          }\n\n          render() {\n            return <>{this.props.children}</>;\n          }\n        }\n\n        hydrate(\n          <div>\n            <Fragment key=\"1\">\n              <TestLifecycle>1a</TestLifecycle>\n              <TestLifecycle>1b</TestLifecycle>\n            </Fragment>\n            <Fragment key=\"2\">\n              <TestLifecycle>2a</TestLifecycle>\n              <TestLifecycle>2b</TestLifecycle>\n            </Fragment>\n          </div>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<div>1a1b2a2b</div>');\n        expect(unmountCounter).toBe(0);\n        expect(mountCounter).toBe(4);\n\n        render(\n          <div>\n            <Fragment key=\"2\">\n              <TestLifecycle>2a</TestLifecycle>\n              <TestLifecycle>2b</TestLifecycle>\n              <TestLifecycle>2c</TestLifecycle>\n            </Fragment>\n            <Fragment key=\"1\">\n              <TestLifecycle>1a</TestLifecycle>\n              <TestLifecycle>1b</TestLifecycle>\n            </Fragment>\n          </div>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<div>2a2b2c1a1b</div>');\n        expect(unmountCounter).toBe(0);\n        expect(mountCounter).toBe(5);\n\n        render(\n          <div>\n            <Fragment key=\"3\">\n              <TestLifecycle>3a</TestLifecycle>\n              <TestLifecycle>3b</TestLifecycle>\n              <TestLifecycle>3c</TestLifecycle>\n            </Fragment>\n            <Fragment key=\"2\">\n              <TestLifecycle>2a</TestLifecycle>\n              <TestLifecycle>2Patched</TestLifecycle>\n            </Fragment>\n          </div>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<div>3a3b3c2a2Patched</div>');\n        expect(unmountCounter).toBe(3);\n        expect(mountCounter).toBe(8);\n      });\n\n      it('Should unmount empty fragments', () => {\n        hydrate(\n          <Fragment>\n            <Fragment />\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('');\n\n        render(\n          <Fragment>\n            <div />\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<div></div>');\n\n        render(\n          <Fragment>\n            <Fragment />\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('');\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should be possible to replace last element in fragment', () => {\n        hydrate(\n          <Fragment>\n            <Fragment>\n              <span>1a</span>\n              <span>1b</span>\n              <div>1c</div>\n            </Fragment>\n            <Fragment>\n              <span>2a</span>\n              <span>2b</span>\n              <span>2c</span>\n            </Fragment>\n            <Fragment />\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<span>1a</span><span>1b</span><div>1c</div><span>2a</span><span>2b</span><span>2c</span>',\n        );\n\n        render(\n          <Fragment>\n            <Fragment>\n              <span>1a</span>\n              <span>1c</span>\n            </Fragment>\n            <Fragment>\n              <span>2a</span>\n              <span>2b</span>\n              <span>2c</span>\n            </Fragment>\n            <Fragment />\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<span>1a</span><span>1c</span><span>2a</span><span>2b</span><span>2c</span>',\n        );\n\n        render(\n          <Fragment>\n            <Fragment />\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('');\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should mount Fragment with invalid children', () => {\n        hydrate(\n          <Fragment>\n            {null}\n            {undefined}\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('');\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should mount Fragment with invalid children #2', () => {\n        function Foobar() {\n          return null;\n        }\n\n        hydrate(\n          <Fragment>\n            {null}\n            <Foobar />\n            {undefined}\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('');\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should mount Fragment with invalid children #2', () => {\n        let add = false;\n\n        function Foobar() {\n          if (add) {\n            return <div>Ok</div>;\n          }\n          return null;\n        }\n\n        hydrate(\n          <Fragment>\n            {null}\n            <Foobar />\n            {undefined}\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('');\n\n        add = true;\n\n        render(\n          <Fragment>\n            {null}\n            <Foobar />\n            {undefined}\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<div>Ok</div>');\n      });\n\n      it('Should be possible to update from 0 to 1', () => {\n        function Foobar() {\n          return <div>Ok</div>;\n        }\n\n        let content = [null];\n\n        hydrate(\n          <Fragment>\n            <span>1</span>\n            <Fragment>{content}</Fragment>\n            <span>2</span>\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<span>1</span><span>2</span>');\n\n        content = [<Foobar />];\n\n        render(\n          <Fragment>\n            <span>1</span>\n            <Fragment>{content}</Fragment>\n            <span>2</span>\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<span>1</span><div>Ok</div><span>2</span>',\n        );\n      });\n\n      it('Should be possible to update from 0 to 1 fragment -> fragment', () => {\n        function Foobar() {\n          return <div>Ok</div>;\n        }\n\n        let content: InfernoNode[] = [];\n\n        hydrate(\n          <Fragment>\n            <span>1</span>\n            <Fragment>{content}</Fragment>\n            <span>2</span>\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<span>1</span><span>2</span>');\n\n        content = [\n          <Fragment>\n            <Foobar />\n          </Fragment>,\n        ];\n\n        render(\n          <Fragment>\n            <span>1</span>\n            <Fragment>{content}</Fragment>\n            <span>2</span>\n          </Fragment>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<span>1</span><div>Ok</div><span>2</span>',\n        );\n      });\n\n      it('Should be possible to mount and patch single component fragment children', () => {\n        let counter = 0;\n\n        class Foobar extends Component {\n          componentWillMount() {\n            counter++;\n          }\n\n          render() {\n            return null;\n          }\n        }\n\n        hydrate(<></>, container);\n\n        expect(container.innerHTML).toBe('');\n\n        render(\n          <>\n            <Foobar />\n          </>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('');\n        expect(counter).toBe(1);\n\n        render(\n          <>\n            <div>Ok</div>\n            <Foobar />\n          </>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<div>Ok</div>');\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should be possible to mount and patch single component fragment children - variation 2', () => {\n        let counter = 0;\n\n        class Foobar extends Component {\n          componentWillMount() {\n            counter++;\n          }\n\n          render() {\n            return null;\n          }\n        }\n\n        let nodes: InfernoNode[] = [];\n\n        hydrate(<>{nodes}</>, container);\n\n        nodes = [<Foobar />];\n\n        render(<>{nodes}</>, container);\n\n        nodes = [<Foobar />, <Foobar />, <Foobar />];\n\n        render(<>{nodes}</>, container);\n\n        nodes = [];\n\n        render(<>{nodes}</>, container);\n\n        expect(container.innerHTML).toBe('');\n        expect(counter).toBe(3);\n\n        render(\n          <>\n            <div>Ok</div>\n            <Foobar />\n          </>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<div>Ok</div>');\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should be possible to patch single fragment child component', () => {\n        let counter = 0;\n\n        class Foobar extends Component {\n          componentWillMount() {\n            counter++;\n          }\n\n          render() {\n            return null;\n          }\n        }\n\n        hydrate(\n          <>\n            <>\n              <Foobar />\n            </>\n            <>\n              <Foobar />\n            </>\n          </>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('');\n        expect(counter).toBe(2);\n\n        render(\n          <>\n            <></>\n            <>\n              <Foobar />\n            </>\n            <>\n              <Foobar />\n            </>\n            <></>\n            <Foobar />\n          </>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('');\n        expect(counter).toBe(4);\n\n        render(\n          <>\n            <div>Ok</div>\n            <Foobar />\n          </>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<div>Ok</div>');\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should be possible to mount and patch single component fragment children', () => {\n        class Foobar extends Component {\n          render() {\n            return null;\n          }\n        }\n\n        hydrate(\n          <>\n            <Foobar />\n          </>,\n          container,\n        );\n\n        render(\n          <>\n            <Foobar />\n          </>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('');\n\n        render(\n          <>\n            <div>Ok</div>\n            <Foobar />\n          </>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<div>Ok</div>');\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n\n      it('Should be possible to mount and patch single component fragment children', () => {\n        class Foobar extends Component {\n          render() {\n            return null;\n          }\n        }\n\n        hydrate(<>{null}</>, container);\n\n        render(\n          <>\n            <Foobar />\n          </>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('');\n\n        render(\n          <>\n            <div>Ok</div>\n            <Foobar />\n          </>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe('<div>Ok</div>');\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n      });\n    }\n\n    describe('empty container', () => {\n      runAllTests();\n    });\n\n    describe('mismatching container', () => {\n      beforeEach(() => {\n        container.innerHTML = '<div>Okay<span>Foo</span></div><em></em>';\n      });\n\n      runAllTests();\n    });\n  });\n\n  describe('SVG elements', () => {\n    it('Should keep SVG children flagged when parent is SVG', () => {\n      class Rect extends Component {\n        constructor(p, c) {\n          super(p, c);\n          this.state = { className: 'foo' };\n        }\n\n        componentDidMount() {\n          this.setState({ className: 'bar' });\n        }\n\n        render() {\n          return createElement('rect', {\n            className: this.state!.className,\n          });\n        }\n      }\n\n      hydrate(\n        <svg>\n          <Rect />\n        </svg>,\n        container,\n      );\n\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe('foo');\n\n      rerender();\n\n      expect(container.firstChild.firstChild.getAttribute('class')).toBe('bar');\n    });\n  });\n\n  it('Should not re-mount after hydrate render render, Github #1426', () => {\n    container.innerHTML = '<div><span>do not replace me</span></div>';\n\n    const span = container.firstChild.firstChild;\n\n    const vtree = h('div', [h('span', 'do not replace me')]);\n\n    hydrate(vtree, container);\n\n    expect(span).toBe(container.firstChild.firstChild);\n\n    render(vtree, container);\n\n    expect(span).toBe(container.firstChild.firstChild);\n\n    const vtree2 = h('div', [h('span', 'do not replace me')]);\n\n    render(vtree2, container);\n\n    expect(span).toBe(container.firstChild.firstChild);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-hydrate/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-hydrate/package.json",
    "content": "{\n  \"name\": \"inferno-hydrate\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Hydrate plugin to inferno. This package can be used to reuse server side rendered html\",\n  \"author\": {\n    \"name\": \"Sampo Kivistö<Havunen>\",\n    \"email\": \"sampo.kivisto@live.fi\",\n    \"url\": \"https://github.com/havunen\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-hydrate\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"files\": [\n    \"index.cjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"keywords\": [\n    \"babel\",\n    \"react\",\n    \"inferno\",\n    \"framework\",\n    \"interfaces\",\n    \"user interfaces\",\n    \"vdom\"\n  ],\n  \"dependencies\": {\n    \"inferno\": \"9.0.11\"\n  },\n  \"devDependencies\": {\n    \"inferno-create-element\": \"9.0.11\",\n    \"inferno-hyperscript\": \"9.0.11\",\n    \"inferno-shared\": \"9.0.11\",\n    \"inferno-vnode-flags\": \"9.0.11\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\",\n      \"inferno-vnode-flags\"\n    ],\n    \"moduleName\": \"Inferno\",\n    \"moduleGlobals\": {\n      \"inferno\": \"Inferno\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno-hydrate/readme.md",
    "content": "# inferno-hydrate\n\nSame as `render()`, but is used to hydrate a container whose HTML contents were rendered by `Inferno-server`. Inferno will attempt to attach event listeners to the existing markup.\n\n## Install\n\n```\nnpm install inferno-hydrate\n```\n\n## Usage\n\n```js\nimport { hydrate } from 'inferno-hydrate';\n\nhydrate(\n  createElement('div', { className: 'test' }, \"I'm a child!\"),\n  document.getElementById('app'),\n);\n```\n"
  },
  {
    "path": "packages/inferno-hydrate/src/index.ts",
    "content": "import {\n  isFunction,\n  isInvalid,\n  isNull,\n  isNullOrUndef,\n  throwError,\n  warning,\n} from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport {\n  _CI,\n  _HI,\n  _M,\n  _MCCC,\n  _ME,\n  _MFCC,\n  _MP,\n  _MR,\n  _RFC as renderFunctionalComponent,\n  AnimationQueues,\n  type ContextObject,\n  EMPTY_OBJ,\n  render,\n  type VNode,\n} from 'inferno';\n\nfunction isSameInnerHTML(dom: Element, innerHTML: string): boolean {\n  const tempdom = document.createElement('i');\n\n  tempdom.innerHTML = innerHTML;\n  return tempdom.innerHTML === dom.innerHTML;\n}\n\nfunction findLastDOMFromVNode(vNode: VNode): Element | null {\n  let flags;\n  let children;\n\n  while (vNode) {\n    flags = vNode.flags;\n\n    if (flags & VNodeFlags.DOMRef) {\n      return vNode.dom;\n    }\n\n    children = vNode.children;\n\n    if (flags & VNodeFlags.Fragment) {\n      vNode =\n        vNode.childFlags === ChildFlags.HasVNodeChildren\n          ? (children as VNode)\n          : (children as VNode[])[children.length - 1];\n    } else if (flags & VNodeFlags.ComponentClass) {\n      vNode = children.$LI;\n    } else {\n      vNode = children;\n    }\n  }\n\n  return null;\n}\n\nfunction isSamePropsInnerHTML(dom: Element, props): boolean {\n  return Boolean(\n    props?.dangerouslySetInnerHTML?.__html &&\n      isSameInnerHTML(dom, props.dangerouslySetInnerHTML.__html),\n  );\n}\n\nfunction hydrateComponent(\n  vNode: VNode,\n  parentDOM: Element,\n  dom: Element,\n  context,\n  isSVG: boolean,\n  isClass: boolean,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): Element | null {\n  const type = vNode.type;\n  const ref = vNode.ref;\n  const props = vNode.props || EMPTY_OBJ;\n  let currentNode: Element | null;\n\n  if (isClass) {\n    const instance = _CI(vNode, type, props, context, isSVG, lifecycle);\n    const input = instance.$LI;\n\n    currentNode = hydrateVNode(\n      input,\n      parentDOM,\n      dom,\n      instance.$CX,\n      isSVG,\n      lifecycle,\n      animations,\n    );\n    _MCCC(ref, instance, lifecycle, animations);\n  } else {\n    const input = _HI(renderFunctionalComponent(vNode, context));\n    currentNode = hydrateVNode(\n      input,\n      parentDOM,\n      dom,\n      context,\n      isSVG,\n      lifecycle,\n      animations,\n    );\n    vNode.children = input;\n    _MFCC(vNode, lifecycle, animations);\n  }\n\n  return currentNode;\n}\n\nfunction hydrateChildren(\n  parentVNode: VNode,\n  parentNode,\n  currentNode,\n  context,\n  isSVG,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): void {\n  const childFlags = parentVNode.childFlags;\n  const children = parentVNode.children;\n  const props = parentVNode.props;\n  const flags = parentVNode.flags;\n\n  if (childFlags !== ChildFlags.HasInvalidChildren) {\n    if (childFlags === ChildFlags.HasVNodeChildren) {\n      if (isNull(currentNode)) {\n        _M(\n          children as VNode,\n          parentNode,\n          context,\n          isSVG,\n          null,\n          lifecycle,\n          animations,\n        );\n      } else {\n        currentNode = hydrateVNode(\n          children as VNode,\n          parentNode,\n          currentNode as Element,\n          context,\n          isSVG,\n          lifecycle,\n          animations,\n        );\n        currentNode = currentNode ? currentNode.nextSibling : null;\n      }\n    } else if (childFlags === ChildFlags.HasTextChildren) {\n      if (isNull(currentNode)) {\n        parentNode.appendChild(document.createTextNode(children as string));\n      } else if (\n        parentNode.childNodes.length !== 1 ||\n        currentNode.nodeType !== 3\n      ) {\n        parentNode.textContent = children as string;\n      } else {\n        if (currentNode.nodeValue !== children) {\n          currentNode.nodeValue = children as string;\n        }\n      }\n      currentNode = null;\n    } else if (childFlags & ChildFlags.MultipleChildren) {\n      let prevVNodeIsTextNode = false;\n\n      for (let i = 0, len = (children as VNode[]).length; i < len; ++i) {\n        const child = (children as VNode[])[i];\n\n        if (\n          isNull(currentNode) ||\n          (prevVNodeIsTextNode && (child.flags & VNodeFlags.Text) > 0)\n        ) {\n          _M(\n            child,\n            parentNode,\n            context,\n            isSVG,\n            currentNode,\n            lifecycle,\n            animations,\n          );\n        } else {\n          currentNode = hydrateVNode(\n            child,\n            parentNode,\n            currentNode as Element,\n            context,\n            isSVG,\n            lifecycle,\n            animations,\n          );\n          currentNode = currentNode ? currentNode.nextSibling : null;\n        }\n\n        prevVNodeIsTextNode = (child.flags & VNodeFlags.Text) > 0;\n      }\n    }\n\n    // clear any other DOM nodes, there should be only a single entry for the root\n    if ((flags & VNodeFlags.Fragment) === 0) {\n      // eslint-disable-next-line no-useless-assignment\n      let nextSibling: Node | null = null;\n\n      while (currentNode) {\n        nextSibling = currentNode.nextSibling;\n        parentNode.removeChild(currentNode);\n        currentNode = nextSibling;\n      }\n    }\n  } else if (\n    !isNull(parentNode.firstChild) &&\n    !isSamePropsInnerHTML(parentNode, props)\n  ) {\n    parentNode.textContent = ''; // dom has content, but VNode has no children remove everything from DOM\n    if (flags & VNodeFlags.FormElement) {\n      // If element is form element, we need to clear defaultValue also\n      parentNode.defaultValue = '';\n    }\n  }\n}\n\nfunction hydrateElement(\n  vNode: VNode,\n  parentDOM: Element,\n  dom: Element,\n  context: ContextObject,\n  isSVG: boolean,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): Element | null {\n  const props = vNode.props;\n  const className = vNode.className;\n  const flags = vNode.flags;\n  const ref = vNode.ref;\n\n  isSVG = isSVG || (flags & VNodeFlags.SvgElement) > 0;\n  if (dom.nodeType !== 1 || dom.tagName.toLowerCase() !== vNode.type) {\n    if (process.env.NODE_ENV !== 'production') {\n      warning(\n        \"Inferno hydration: Server-side markup doesn't match client-side markup\",\n      );\n    }\n    _ME(vNode, null, context, isSVG, null, lifecycle, animations);\n    parentDOM.replaceChild(vNode.dom as Element, dom);\n  } else {\n    vNode.dom = dom;\n\n    hydrateChildren(\n      vNode,\n      dom,\n      dom.firstChild,\n      context,\n      isSVG,\n      lifecycle,\n      animations,\n    );\n\n    if (!isNull(props)) {\n      _MP(vNode, flags, props, dom, isSVG, animations);\n    }\n    if (isNullOrUndef(className)) {\n      if (dom.className !== '') {\n        dom.removeAttribute('class');\n      }\n    } else if (isSVG) {\n      dom.setAttribute('class', className);\n    } else {\n      dom.className = className;\n    }\n    _MR(ref, dom, lifecycle);\n  }\n\n  return vNode.dom;\n}\n\nfunction hydrateText(\n  vNode: VNode,\n  parentDOM: Element,\n  dom: Element,\n): Element | null {\n  if (dom.nodeType !== 3) {\n    parentDOM.replaceChild(\n      (vNode.dom = document.createTextNode(vNode.children as string) as any),\n      dom,\n    );\n  } else {\n    const text = vNode.children;\n\n    if (dom.nodeValue !== text) {\n      dom.nodeValue = text as string;\n    }\n    vNode.dom = dom;\n  }\n\n  return vNode.dom;\n}\n\nfunction hydrateFragment(\n  vNode: VNode,\n  parentDOM: Element,\n  dom: Element,\n  context,\n  isSVG: boolean,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): Element {\n  const children = vNode.children;\n\n  if (vNode.childFlags === ChildFlags.HasVNodeChildren) {\n    hydrateText(children as VNode, parentDOM, dom);\n\n    return (children as VNode).dom as Element;\n  }\n\n  hydrateChildren(vNode, parentDOM, dom, context, isSVG, lifecycle, animations);\n\n  return findLastDOMFromVNode(\n    (children as VNode[])[(children as VNode[]).length - 1],\n  ) as Element;\n}\n\nfunction hydrateVNode(\n  vNode: VNode,\n  parentDOM: Element,\n  currentDom: Element,\n  context: ContextObject,\n  isSVG: boolean,\n  lifecycle: Array<() => void>,\n  animations: AnimationQueues,\n): Element | null {\n  const flags = (vNode.flags |= VNodeFlags.InUse);\n\n  if (flags & VNodeFlags.Component) {\n    return hydrateComponent(\n      vNode,\n      parentDOM,\n      currentDom,\n      context,\n      isSVG,\n      (flags & VNodeFlags.ComponentClass) > 0,\n      lifecycle,\n      animations,\n    );\n  }\n  if (flags & VNodeFlags.Element) {\n    return hydrateElement(\n      vNode,\n      parentDOM,\n      currentDom,\n      context,\n      isSVG,\n      lifecycle,\n      animations,\n    );\n  }\n  if (flags & VNodeFlags.Text) {\n    return hydrateText(vNode, parentDOM, currentDom);\n  }\n  if (flags & VNodeFlags.Fragment) {\n    return hydrateFragment(\n      vNode,\n      parentDOM,\n      currentDom,\n      context,\n      isSVG,\n      lifecycle,\n      animations,\n    );\n  }\n\n  if (process.env.NODE_ENV !== 'production') {\n    throwError(\n      `hydrate() expects a valid VNode, instead it received an object with the type \"${typeof vNode}\".`,\n    );\n  }\n  throwError();\n\n  return null;\n}\n\nexport function hydrate(\n  input,\n  parentDOM: Element,\n  callback?: () => void,\n): void {\n  let dom: Element | null = parentDOM.firstChild as Element;\n\n  if (isNull(dom)) {\n    if (process.env.NODE_ENV !== 'production') {\n      warning(\n        \"Inferno hydration: Server-side markup doesn't match client-side markup\",\n      );\n    }\n    render(input, parentDOM, callback);\n  } else {\n    const lifecycle: Array<() => void> = [];\n    const animations: AnimationQueues = new AnimationQueues();\n\n    if (!isInvalid(input)) {\n      dom = hydrateVNode(\n        input,\n        parentDOM,\n        dom,\n        {},\n        false,\n        lifecycle,\n        animations,\n      ) as Element;\n    }\n    // clear any other DOM nodes, there should be only a single entry for the root\n\n    while (dom && (dom = dom.nextSibling as Element | null)) {\n      parentDOM.removeChild(dom);\n    }\n\n    if (lifecycle.length > 0) {\n      let listener;\n      while ((listener = lifecycle.shift()) !== undefined) {\n        listener();\n      }\n    }\n  }\n\n  (parentDOM as any).$V = input;\n\n  if (isFunction(callback)) {\n    callback();\n  }\n}\n"
  },
  {
    "path": "packages/inferno-hyperscript/README.md",
    "content": "# inferno-hyperscript\n\n> [Hyperscript][hyperscript] syntax for [Inferno][inferno] termplates.\n\n## Usage\n\n```javascript\nvar h = require('inferno-hyperscript');\n\nmodule.exports = function ExampleComponent(props) {\n  return h('.example', [\n    h(\n      'a.example-link',\n      {\n        href: '#',\n      },\n      ['Hello', props.whom, '!'],\n    ),\n  ]);\n};\n```\n\n## Documentation\n\n### `h(componentOrTag, properties, children, noNormalize)`\n\nReturns an Inferno VNode from a Hyperscript representation.\n\n- **componentOrTag** `(Object|String)` can be an Inferno component **OR** tag string with optional css class names and ids in the format `h1#some-id.foo.bar`.\n  If a tag string, the tag name is parsed out, and the `id` and `className` propertires of the properties argument will be modified.\n- **properties** `(Object)` _(optional)_ An object containing the properties you'd like to set on the element.\n- **children** `(Array|String)` _(optional)_ An array of `h()` children or strings, This will create childen or text nodes respectively.\n  New in v4.0.0\n- **noNormalize** Boolean _(optional)_ Set true to avoid normalization process. Tells Inferno to trust the input as is. Used for optimization.\n\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[inferno]: https://github.com/infernojs/inferno\n"
  },
  {
    "path": "packages/inferno-hyperscript/__tests__/hyperscript.spec.tsx",
    "content": "import { h } from 'inferno-hyperscript';\nimport {\n  Component,\n  createRef,\n  forwardRef,\n  Fragment,\n  RefObject,\n  render,\n} from 'inferno';\n\ndescribe('HyperScript (non-JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should handle a basic example', () => {\n    render(h('div'), container);\n    expect(container.innerHTML).toBe('<div></div>');\n  });\n\n  it('Should handle a basic example #2', () => {\n    render(h('div', 'Hello world!'), container);\n    expect(container.innerHTML).toBe('<div>Hello world!</div>');\n  });\n\n  it('Should handle a basic example #3', () => {\n    render(h('div', { className: 'foo' }, 'Hello world!'), container);\n    expect(container.innerHTML).toBe('<div class=\"foo\">Hello world!</div>');\n  });\n\n  const StatelessComponent = () => h('div', 'Hello world!');\n\n  describe('Class Component hooks', function () {\n    it('Should trigger ref callback when component is mounting and unmounting', () => {\n      const container = document.createElement('div');\n      class FooBar extends Component {\n        render() {\n          return h('div');\n        }\n      }\n      const spyObj = {\n        fn: () => {},\n      };\n      const spy = spyOn(spyObj, 'fn');\n      const node = h(FooBar, { ref: spyObj.fn });\n\n      render(node, container);\n\n      expect(spy.calls.count()).toBe(1);\n      expect(spy.calls.argsFor(0).length).toBe(1);\n      expect(spy.calls.argsFor(0)[0]).not.toEqual(null);\n\n      render(null, container);\n\n      expect(spy.calls.count()).toBe(2);\n      expect(spy.calls.argsFor(1).length).toBe(1);\n      expect(spy.calls.argsFor(1)[0]).toEqual(null);\n    });\n  });\n\n  it('Should handle a basic example #4', () => {\n    render(h(StatelessComponent), container);\n    expect(container.innerHTML).toBe('<div>Hello world!</div>');\n  });\n\n  it('Should handle a hooks example #1', () => {\n    const Component = ({ children }) => {\n      return h('div', children);\n    };\n    const ComponentHooks = () =>\n      h(Component, {\n        hooks: {\n          onComponentDidUnmount() {},\n        },\n        children: 'Hello world!',\n      });\n\n    render(h(ComponentHooks), container);\n    expect(container.innerHTML).toBe('<div>Hello world!</div>');\n  });\n\n  it('Should handle children as third argument', () => {\n    const Component = ({ children }) => {\n      return h('div', children);\n    };\n    const ComponentHooks = () => h(Component, null, 'Hello world!');\n\n    render(h(ComponentHooks), container);\n    expect(container.innerHTML).toBe('<div>Hello world!</div>');\n  });\n\n  it('Should handle different props (key, class, id, ref, children)', () => {\n    const ComponentHooks = () =>\n      h('div#myId.test', {\n        onComponentDidMount() {},\n        key: 'myKey',\n        ref: (c) => c,\n        className: 'myClass',\n        children: 'Hello world!',\n      });\n\n    render(h(ComponentHooks), container);\n    expect(container.innerHTML).toBe(\n      '<div class=\"test myClass\" id=\"myId\">Hello world!</div>',\n    );\n  });\n\n  it('Should handle tag with no name', () => {\n    const ComponentHooks = () => h('', { children: 'Hello world!' });\n    render(h(ComponentHooks), container);\n    expect(container.innerHTML).toBe('<div>Hello world!</div>');\n  });\n\n  it('Should be possible to create textarea with hyperscript', () => {\n    const ComponentHooks = () => h('textarea', { id: 'test' });\n    render(h(ComponentHooks), container);\n    expect(container.innerHTML).toBe('<textarea id=\"test\"></textarea>');\n  });\n\n  it('Should be possible to create select element with hyperscript', () => {\n    const ComponentHooks = () =>\n      h('select', { id: 'select' }, [\n        h('option', { value: 1 }, '1'),\n        h('option', { value: 2 }, '2'),\n      ]);\n    render(h(ComponentHooks), container);\n    expect(container.innerHTML).toBe(\n      '<select id=\"select\"><option value=\"1\">1</option><option value=\"2\">2</option></select>',\n    );\n  });\n\n  it('Should handle tag with no tag name but id is present', () => {\n    const ComponentHooks = () => h('#myId');\n    render(h(ComponentHooks), container);\n    expect(container.innerHTML).toBe('<div id=\"myId\"></div>');\n  });\n\n  it('Should support lifecycle methods on functional components willMount', () => {\n    const callbackSpy = jasmine.createSpy('spy');\n    const ComponentHooks = () => h('#myId');\n    render(h(ComponentHooks, { onComponentWillMount: callbackSpy }), container);\n    expect(container.innerHTML).toBe('<div id=\"myId\"></div>');\n    expect(callbackSpy).toHaveBeenCalledTimes(1);\n  });\n\n  it('Should support lifecycle methods on functional components didMount', () => {\n    const callbackSpy = jasmine.createSpy('spy');\n    const ComponentHooks = () => h('#myId');\n    render(h(ComponentHooks, { onComponentDidMount: callbackSpy }), container);\n    expect(container.innerHTML).toBe('<div id=\"myId\"></div>');\n    expect(callbackSpy).toHaveBeenCalledTimes(1);\n  });\n\n  it('Should pass classNames through', () => {\n    function Test1({ children, ...props }) {\n      return h('div.test1', props, children);\n    }\n\n    function Test2({ children, ...props }) {\n      return h('div', props, children);\n    }\n\n    function Test3({ children }) {\n      return h('div', { className: 'test3' }, children);\n    }\n\n    function Test4({ children, className, ...props }) {\n      return h('div', { className, ...props }, children);\n    }\n\n    render(\n      h('div', {}, [\n        h(Test1, { className: 'test1prop' }),\n        h(Test2, { className: 'test2prop' }),\n        h(Test3),\n        h(Test4, { className: 'test4prop' }),\n      ]),\n      container,\n    );\n\n    const children = container.firstChild.childNodes;\n\n    expect(children[0].className).toBe('test1 test1prop');\n    expect(children[1].className).toBe('test2prop');\n    expect(children[2].className).toBe('test3');\n    expect(children[3].className).toBe('test4prop');\n  });\n\n  if (typeof global !== 'undefined' && !global.usingJSDOM) {\n    it('Should not lower case SVG tags', () => {\n      render(\n        h(\n          'svg',\n          null,\n          h(\n            'filter',\n            { id: 'blur' },\n            h('feGaussianBlur', { in: 'SourceGraphic' }),\n          ),\n        ),\n        container,\n      );\n\n      expect(container.firstChild.firstChild.firstChild.tagName).toEqual(\n        'feGaussianBlur',\n      ); // tag name is case sensitive\n      expect(container.firstChild.firstChild.tagName).toEqual('filter');\n      expect(container.firstChild.tagName).toEqual('svg');\n    });\n  }\n\n  describe('CreateElement variations (non-JSX)', () => {\n    it('Should handle events correctly when having multiple children', () => {\n      let triggered = false;\n\n      const App = () => {\n        return h('div', null, [\n          h('div', { className: 'title' }, 'Example'),\n          h(\n            'button',\n            {\n              type: 'button',\n              onClick: () => {\n                triggered = !triggered;\n              },\n            },\n            'Do a thing',\n          ),\n        ]);\n      };\n\n      render(App(), container);\n      expect(container.innerHTML).toBe(\n        '<div><div class=\"title\">Example</div><button type=\"button\">Do a thing</button></div>',\n      );\n      expect(triggered).toBe(false);\n\n      const buttons = container.querySelectorAll('button');\n      for (const button of buttons) {\n        button.click();\n      }\n\n      expect(triggered).toBe(true);\n    });\n\n    it('Should handle events correctly when having single child', () => {\n      let triggered = false;\n\n      const app = () => {\n        return h(\n          'div',\n          null,\n          h(\n            'button',\n            {\n              type: 'button',\n              onClick: () => {\n                triggered = !triggered;\n              },\n            },\n            'Do a thing',\n          ),\n        );\n      };\n\n      render(app(), container);\n      expect(container.innerHTML).toBe(\n        '<div><button type=\"button\">Do a thing</button></div>',\n      );\n      expect(triggered).toBe(false);\n\n      const buttons = container.querySelectorAll('button');\n      for (const button of buttons) {\n        button.click();\n      }\n\n      expect(triggered).toBe(true);\n    });\n\n    it('Should allow passing childs through \"children\" property (native component)', () => {\n      const app = () => {\n        return h(\n          'div',\n          null,\n          h('button', {\n            type: 'button',\n            children: ['Do a thing'],\n          }),\n        );\n      };\n\n      render(app(), container);\n      expect(container.innerHTML).toBe(\n        '<div><button type=\"button\">Do a thing</button></div>',\n      );\n    });\n\n    it('Should allow passing childs through \"children\" property (custom component)', () => {\n      const Button = (props) => h('button', props);\n      const app = () => {\n        return h(\n          'div',\n          null,\n          h(Button, {\n            type: 'button',\n            children: ['Do a thing'],\n          }),\n        );\n      };\n\n      render(app(), container);\n      expect(container.innerHTML).toBe(\n        '<div><button type=\"button\">Do a thing</button></div>',\n      );\n    });\n\n    it('Should handle node with hooks and key', (done) => {\n      const node = () => h('div', { key: 'key2' }, 'Hooks');\n      const app = h(node, {\n        key: 'key1',\n        onComponentDidMount(domNode) {\n          expect(app.key).toBe('key1');\n          expect(domNode.tagName).toBe('DIV');\n          done();\n        },\n      });\n\n      render(app, container);\n      expect(container.innerHTML).toBe('<div>Hooks</div>');\n    });\n\n    it('Should handle node with children but no props', () => {\n      const node = () => h('div', null, 'Hooks');\n      const app = h(node, null, 'Hooks');\n\n      render(app, container);\n      expect(container.innerHTML).toBe('<div>Hooks</div>');\n    });\n\n    it('Should handle node with refs', (done) => {\n      let myRef;\n\n      const app = () => {\n        const node = () =>\n          h('a', {\n            ref: (c) => (myRef = c),\n          });\n        return h(node, {\n          onComponentDidMount() {\n            expect(myRef.tagName).toBe('A');\n            done();\n          },\n        });\n      };\n      render(h(app, null), container);\n    });\n\n    let shouldUpdate = false;\n\n    class Test2 extends Component<{ foo: string }> {\n      shouldComponentUpdate() {\n        return shouldUpdate;\n      }\n\n      render() {\n        return h('div', { contenteditable: true }, this.props.foo);\n      }\n    }\n\n    it('Should not fail contenteditable if text node has external change Github#1207 - createElement', () => {\n      shouldUpdate = false;\n      render(<Test2 foo=\"bar\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">bar</div>');\n      render(<Test2 foo=\"yar\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">bar</div>');\n\n      container.firstChild.removeChild(container.firstChild.firstChild); // When div is contentEditable user can remove whole text content\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\"></div>');\n\n      shouldUpdate = true;\n      render(<Test2 foo=\"foo\" />, container);\n      expect(container.innerHTML).toBe('<div contenteditable=\"true\">foo</div>');\n      render(null, container);\n      expect(container.innerHTML).toBe('');\n    });\n  });\n\n  describe('Fragments', () => {\n    it('Should render Fragment with key', () => {\n      render(\n        h(Fragment, { key: 'first' }, [\n          h('div', null, 'Ok'),\n          h('span', null, 'Test'),\n        ]),\n        container,\n      );\n\n      expect(container.innerHTML).toBe('<div>Ok</div><span>Test</span>');\n\n      const div = container.querySelector('div');\n      const span = container.querySelector('span');\n\n      render(\n        h(Fragment, { key: 'foobar' }, [\n          h('div', null, 'Ok'),\n          h('span', null, 'Test'),\n        ]),\n        container,\n      );\n\n      // Verify key works\n      expect(container.innerHTML).toBe('<div>Ok</div><span>Test</span>');\n\n      expect(div).not.toBe(container.querySelector('div'));\n      expect(span).not.toBe(container.querySelector('span'));\n    });\n  });\n\n  it('Should be possible to forward createRef', () => {\n    const FancyButton = forwardRef((props, ref) =>\n      h('button', { ref, className: 'FancyButton' }, props.children),\n    );\n\n    expect(FancyButton.render).toBeDefined();\n\n    class Hello extends Component {\n      private readonly btn: RefObject<Element>;\n\n      constructor(props) {\n        super(props);\n\n        // You can now get a ref directly to the DOM button:\n        this.btn = createRef();\n      }\n\n      componentDidMount() {\n        expect(this.btn.current).toBe(container.querySelector('button'));\n      }\n\n      render() {\n        return h(FancyButton, { ref: this.btn }, 'Click me!');\n      }\n    }\n\n    render(h(Hello), container);\n\n    expect(container.innerHTML).toBe(\n      '<button class=\"FancyButton\">Click me!</button>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-hyperscript/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-hyperscript/package.json",
    "content": "{\n  \"name\": \"inferno-hyperscript\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Bridging hyperscript to InfernoJS\",\n  \"author\": \"Terin Stock <terinjokes@gmail.com> (https://terinstock.com/)\",\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"files\": [\n    \"index.cjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"keywords\": [\n    \"inferno\",\n    \"hyperscript\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-hyperscript\"\n  },\n  \"dependencies\": {\n    \"inferno\": \"9.0.11\"\n  },\n  \"devDependencies\": {\n    \"inferno-shared\": \"9.0.11\",\n    \"inferno-vnode-flags\": \"9.0.11\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\",\n      \"inferno-vnode-flags\"\n    ],\n    \"moduleName\": \"Inferno\",\n    \"moduleGlobals\": {\n      \"inferno\": \"Inferno\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno-hyperscript/src/index.ts",
    "content": "import {\n  createComponentVNode,\n  createFragment,\n  createVNode,\n  Fragment,\n  getFlagsForElementVnode,\n  type InfernoNode,\n  type VNode,\n} from 'inferno';\nimport {\n  isArray,\n  isString,\n  isStringOrNumber,\n  isUndefined,\n} from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\n\nconst classIdSplit = /([.#]?[a-zA-Z0-9_:-]+)/;\nconst notClassId = /^\\.|#/;\n\nfunction parseTag(tag: string | null, props: any): string {\n  if (!tag) {\n    return 'div';\n  }\n  if (tag === (Fragment as any)) {\n    return tag;\n  }\n  const noId = props && isUndefined(props.id);\n  const tagParts = tag.split(classIdSplit);\n  let tagName: null | string = null;\n\n  if (notClassId.test(tagParts[1])) {\n    tagName = 'div';\n  }\n  let classes;\n\n  for (let i = 0, len = tagParts.length; i < len; ++i) {\n    const part = tagParts[i];\n\n    if (!part) {\n      continue;\n    }\n    const type = part.charAt(0);\n\n    if (!tagName) {\n      tagName = part;\n    } else if (type === '.') {\n      if (classes === void 0) {\n        classes = [];\n      }\n      classes.push(part.substring(1, part.length));\n    } else if (type === '#' && noId) {\n      props.id = part.substring(1, part.length);\n    }\n  }\n  if (classes) {\n    if (props.className) {\n      classes.push(props.className);\n    }\n    props.className = classes.join(' ');\n  }\n  return tagName || 'div';\n}\n\nfunction isChildren(x: any): boolean {\n  return isStringOrNumber(x) || (x && isArray(x));\n}\n\n/**\n * Creates virtual node\n * @param {string|VNode|Function} _tag Name for virtual node\n * @param {object=} _props Additional properties for virtual node\n * @param {string|number|VNode|Array<string|number|VNode>|null=} _children Optional children for virtual node\n * @returns {VNode} returns new virtual node\n */\nexport function h(\n  _tag: string | VNode | Function,\n  _props?: any,\n  _children?: InfernoNode,\n): VNode {\n  // If a child array or text node are passed as the second argument, shift them\n  if (!_children && isChildren(_props)) {\n    _children = _props;\n    _props = {};\n  }\n  const isElement = isString(_tag);\n  _props = _props || {};\n  const tag = isElement ? parseTag(_tag, _props) : _tag;\n  const newProps: any = {};\n  let key = null;\n  let ref: any = null;\n  let children = null;\n  let className = null;\n\n  for (const prop in _props) {\n    if (isElement && (prop === 'className' || prop === 'class')) {\n      className = _props[prop];\n    } else if (prop === 'key') {\n      key = _props[prop];\n    } else if (prop === 'ref') {\n      ref = _props[prop];\n    } else if (prop === 'hooks') {\n      ref = _props[prop];\n    } else if (prop === 'children') {\n      children = _props[prop];\n    } else if (!isElement && prop.substr(0, 11) === 'onComponent') {\n      if (!ref) {\n        ref = {};\n      }\n      ref[prop] = _props[prop];\n    } else {\n      newProps[prop] = _props[prop];\n    }\n  }\n\n  if (isElement) {\n    let flags = getFlagsForElementVnode(tag as string);\n\n    if (flags & VNodeFlags.Fragment) {\n      return createFragment(\n        _children || children,\n        ChildFlags.UnknownChildren,\n        key,\n      );\n    }\n\n    if (newProps.contenteditable !== void 0) {\n      flags |= VNodeFlags.ContentEditable;\n    }\n\n    return createVNode(\n      flags,\n      tag as string,\n      className,\n      _children || children,\n      ChildFlags.UnknownChildren,\n      newProps,\n      key,\n      ref,\n    );\n  }\n\n  if (children || _children) {\n    newProps.children = children || _children;\n  }\n\n  return createComponentVNode(\n    VNodeFlags.ComponentUnknown,\n    tag as any,\n    newProps,\n    key,\n    ref,\n  );\n}\n"
  },
  {
    "path": "packages/inferno-mobx/README.md",
    "content": "# inferno-mobx\n\nThis is a fork of [mobx-react](https://github.com/mobxjs/mobx-react) for [Inferno](https://github.com/infernojs/inferno)\n\nThe module is compatible with Inferno v1+, for older versions use [mobx-inferno](https://www.npmjs.com/package/mobx-inferno)\n\nThis package provides the bindings for MobX and Inferno.\nExports `observer` and `inject` decorators, a `Provider` and some development utilities.\n\n_New_: exports `observerPatch`, a function to turn Component classes into MobX observers.\n`observerPatch` is implemented in a better manner, but is separate as it would break compatibility in some cases.\n\n_New_: exports `observerWrap`, a function to turn functional Components into MobX observers.\nUnlike `observer`, `observerWrap` does not wrap them in a class Component.\nThis allows the base Component and the observer to be interchangable.\n\n## Install\n\n```\nnpm install --save inferno-mobx\n```\n\nAlso install [mobx](https://github.com/mobxjs/mobx) dependency _(required)_ if you don't already have it\n\n```\nnpm install --save mobx\n```\n\n## observerPatch Examples\n\nPass a class Component to `observerPatch` to have in automatically re-render if MobX observables read by `render` are modified.\n\n```tsx\n// MyComponent.tsx (also works with plain JavaScript)\nimport { Component } from 'inferno';\nimport { observerPatch } from 'inferno-mobx';\n\ninterface CountStore {\n  readonly count: number;\n}\n\nexport class MyComponentA extends Component<{ countStore: CountStore }> {\n  render({ countStore }: { countStore: CountStore }) {\n    return <p>Current Count: {countStore.count.toString()}</p>;\n  }\n}\n\nobserverPatch(MyComponentA);\n\n// Or you can use functions that read from stores instead of the stores\nexport class MyComponentB extends Component<{ count: () => number }> {\n  render({ count }: { count: () => number }) {\n    return <p>Current Count: {count().toString()}</p>;\n  }\n}\n\nobserverPatch(MyComponentB);\n\n// However, passing a value from an observable directly as a property will NOT work!\nexport class MyComponentC extends Component<{ count: number }> {\n  render({ count }: { count: number }) {\n    return <p>Current Count: {count.toString()}</p>;\n  }\n}\n\nobserverPatch(MyComponentC);\n\nfunction MyComponentF({ count }: { count: () => number }) {\n  return <p>Current Count: {count().toString()}</p>;\n}\n\n// Detection does NOT cross component boundaries. So this does NOT work:\nexport class MyComponentD extends Component<{ countStore: CountStore }> {\n  render({ countStore }: { countStore: CountStore }) {\n    return (\n      <div className=\"fancy\">\n        <MyComponentF count={() => countStore.count} />\n      </div>\n    );\n  }\n}\n\nobserverPatch(MyComponentD);\n\n// You can use simple functional components as functions:\nexport class MyComponentE extends Component<{ countStore: CountStore }> {\n  render({ countStore }: { countStore: CountStore }) {\n    // But keep in mind that the whole component will re-render.\n    return (\n      <div className=\"fancy\">\n        {MyComponentF({ count: () => countStore.count })}\n      </div>\n    );\n  }\n}\n\nobserverPatch(MyComponentE);\n\n// Only Components that depend on MobX observables need to be observers.\nexport class MyComponentG extends Component<{ countStore: CountStore }> {\n  render({ countStore }: { countStore: CountStore }) {\n    // MyComponentB is an observer and will re-render when countStore.count changes.\n    return (\n      <div className=\"fancy\">\n        <MyComponentB count={() => countStore.count} />\n      </div>\n    );\n  }\n}\n\n// observerPatch(MyComponentG) is not needed and would add overhead for no reason.\n\n// If you want both an observer and a non observer versions of a component,\n// then you can just extend the non observer and patch the sub class.\nexport class MyComponentH extends Component<{ count: () => number }> {\n  // non observer base class\n  render({ count }: { count: () => number }) {\n    return <p>Current Count: {count().toString()}</p>;\n  }\n}\n\nexport class MyComponentI extends MyComponentH {} // sub class indended to be an observer\nobserverPatch(MyComponentI); // make the sub class an observer\n\n// DO NOT extend from Components that are obsevers.\n// If you do have reason to extend a Component class that will be an observer,\n// see above on how to easily have both an obsever and a non-observer version.\nexport class MyComponentJ extends MyComponentA {\n  render(properties: { countStore: CountStore }) {\n    return <div className=\"fancy\">{super.render(properties)}</div>;\n  }\n}\n\n// Even if you do not call observerPatch on the sub class, extending\n// from observers can create problems.\nobserverPatch(MyComponentJ);\n\n// DO NOT call observerPatch more than once on a clase.\nexport class MyComponentK extends Component<{ countStore: CountStore }> {\n  render({ countStore }: { countStore: CountStore }) {\n    return <p>Current Count: {countStore.count.toString()}</p>;\n  }\n}\n\nobserverPatch(MyComponentK);\nobserverPatch(MyComponentK); // NEVER call more than once per class!\n```\n\n```tsx\n// index.tsx\nimport {\n  MyComponentA,\n  MyComponentB,\n  MyComponentC,\n  MyComponentD,\n  MyComponentE,\n  MyComponentG,\n  MyComponentH,\n  MyComponentI,\n  MyComponentJ,\n  MyComponentK,\n} from './MyComponent';\nimport { render } from 'inferno';\nimport { action, observable } from 'mobx';\n\nconst store = observable({ count: 0 });\n\nrender(\n  <div>\n    <MyComponentA countStore={store} />\n    <MyComponentB count={() => store.count} />\n    <MyComponentC count={store.count} />{' '}\n    {/* This component WILL NOT detect when count changes! */}\n    <MyComponentD countStore={store} />{' '}\n    {/* This component WILL NOT detect when count changes! */}\n    <MyComponentE countStore={store} />\n    <MyComponentG countStore={store} />\n    <MyComponentH count={() => store.count} />{' '}\n    {/* Not an observer so no updating when count changes. */}\n    <MyComponentI count={() => store.count} />{' '}\n    {/* Is an observer so it will update. */}\n    <MyComponentJ countStore={store} />{' '}\n    {/* Works... BUT! when it unmounts there will be an error! */}\n    <MyComponentK countStore={store} />{' '}\n    {/* Works... BUT! when it unmounts there will be an error! */}\n    <button\n      type=\"button\"\n      onClick={action(() => {\n        store.count += 1;\n      })}\n    >\n      Click Me\n    </button>\n  </div>,\n  document.getElementById('components'),\n);\n```\n\nNOTES:\n\n`observerPatch` installs a `componentWillUnmount` hook to dispose of the MobX Reaction.\nIt will then call the `componentWillUnmount` from the class's prototype.\nIf you dynamically add a `componentWillUnmount` to a class you pass to `observerPatch`, be sure it calls the hook installed by `observerPatch`.\n\n`observerPatch` also replaces the `render` method in the prototype.\nThe `render` method gets replaced twice on a per instance basis during the life cycle of a Component.\nIt is replaced the first time `render` is called with a version that is wrapped in a MobX reaction.\nThen it is restored to the class's original `render` method when `componentWillUnmount` is called.\n\nIt is strongly recommended to avoid replacing the `render` method on classes `observerPatch` is applied to.\n\n## observerWrap Examples\n\n`observerWrap` is the companion to `observerPatch`, but for functional Components.\n\n```tsx\n// MyComponent.tsx (also works with plain JavaScript)\nimport { observerWrap } from 'inferno-mobx';\n\ninterface CountStore {\n  readonly count: number;\n}\n\n// For a good debugging experience, have named functions\nfunction MyComponentA({ countStore }: { countStore: CountStore }) {\n  return <p>Current Count: {countStore.count.toString()}</p>;\n}\n\n// If you prefer arrow functions, assign them to a const before passing to observerWrap\nconst MyComponentB = ({ countStore }: { countStore: CountStore }) => {\n  return <p>Current Count: {countStore.count.toString()}</p>;\n};\n\n// This works, but if you need to debug the MobX reactions things will be less nice\nconst MyComponentC = observerWrap(\n  ({ countStore }: { countStore: CountStore }) => {\n    return <p>Current Count: {countStore.count.toString()}</p>;\n  },\n);\n\nconst MyObserverB = observerWrap(MyComponentB);\n\n// double wrapping does not cause errors, but is inefficient\n// a warning will be logged for non-production builds\nconst MyComponentD = observerWrap(MyComponentC);\n\nconst MyComponentE = observerWrap(MyComponentA);\n\n// calling observerWrap on the same component multiple times is fine\nconst MyComponentF = observerWrap(MyComponentA);\n\n// but storing the result of the first call for reuse is still better\n// as each wrapper will take memory\nconst MyComponentG = MyComponentE;\n\nexport {\n  // wrapping separately allow the non-observer component to be used\n  MyComponentA, // not an observer\n  MyObserverB as MyComponentB, // export observer under name of the component\n  MyComponentC,\n  MyComponentD,\n  MyComponentE, // observer version of MyComponentA\n  MyComponentF,\n  MyComponentG,\n};\n```\n\nEverything mentioned for `observerPatch` about passing you observables to the components applies to `observerWrap`.\n\nAs a note, the function returned by `observerWrap` should _only_ be used for constructing Inferno VNodes.\nThat means JSX, `createElement`, inferno-hyperscript, or `createComponentVNode`.\nFor any other usage, you should use the base function directly.\n\n```tsx\n// index.tsx\nimport {\n  MyComponentA,\n  MyComponentB,\n  MyComponentC,\n  MyComponentD,\n  MyComponentE,\n  MyComponentF,\n  MyComponentG,\n} from './MyComponent';\nimport { render } from 'inferno';\nimport { action, observable } from 'mobx';\n\nconst store = observable({ count: 0 });\n\n// All but MyComponentA will update when count changes\n// MyComponentA was not wrapped\nrender(\n  <div>\n    <MyComponentA countStore={store} />\n    <MyComponentB countStore={store} />\n    <MyComponentC countStore={store} />\n    <MyComponentD countStore={store} />\n    <MyComponentE countStore={store} />\n    <MyComponentF countStore={store} />\n    <MyComponentG countStore={store} />\n    <button\n      type=\"button\"\n      onClick={action(() => {\n        store.count += 1;\n      })}\n    >\n      Click Me\n    </button>\n  </div>,\n  document.getElementById('components'),\n);\n```\n\nThere are a few things to say about `defaultHooks` and `defaultProps`.\n\n```typescript\nimport { observerWrap } from 'inferno-mobx';\n\n// For this first component, both the base function and the wrapper will share default hooks and props\nfunction MyComponentA(props) { /* ... */ }\nMyComponentA.defaultHooks = { /* ... */ }\nMyComponentA.defaultProps = { /* ... */ }\nconst MyObserverA = observerWrap(MyComponentA);\n// MyComponentA.defaultHooks === MyObserverA.defaultHooks &&\n// MyComponentA.defaultProps === MyObserverA.defaultProps\n\n// So the following would affect the defaultHooks for both as they refer to the same object:\nMyComponentA.defaultHooks.onComponentShouldUpdate = /* hook */;\n\n// But settting a new object only affects the one being set:\nMyObserverA.defaultProps = { /* ... */ } // Now MyComponentA.defaultProps !== MyObserverA.defaultProps\n\n// If the defaults are set after the wrapper is made, the observer will not have default Hooks nor Props\nfunction MyComponentB(props) { /* ... */ }\nconst MyObserverB = observerWrap(MyComponentB);\nMyComponentB.defaultHooks = { /* ... */ }\nMyComponentB.defaultProps = { /* ... */ }\n// MyObserverB.defaultHooks === undefined && MyObserverB.defaultProps === undefined\n\n// Setting defaults on the observer does not affect the base component\nfunction MyComponentC(props) { /* ... */ }\nconst MyObserverC = observerWrap(MyComponentC);\nMyObserverC.defaultHooks = { /* ... */ }\nMyObserverC.defaultProps = { /* ... */ }\n// MyComponentC.defaultHooks === undefined && MyComponentC.defaultProps === undefined\n```\n\nGenerally the first example is what you want. The third is fine if you only use the observer.\n\nThe most like case you would want the defaults to be different is for the `onComponentShouldUpdate` hook.\nThis is because the re-rendering of the observer is more expensive than the base component.\nThat does not mean you always want `onComponentShouldUpdate` for observers and never to base components.\nBut it can be worth having on observers even if it is not for the base.\n\nNote:\nThe MobX Reaction will call `onComponentWillUpdate` and `onComponentDidUpdate` when re-rendering, if present.\nWhen called by the Reaction the 'previous' and 'next' parameters will be passed the same object.\n\n_Warning_:\nThe `onComponentWillUpdate` and `onComponentDidUpdate` are bound when the component is rendered by Inferno.\nThe `onComponentShouldUpdate` can prevent the binding from being updated if new callbacks are assigned.\n\nTo have a default hook (or property) on just the observer, you need to create a new object that is a copy of the base version.\nAnd then add the new hook or property.\n\n```typescript\nfunction MyComponent(props) {\n  /* ... */\n}\nMyComponent.defaultHooks = {\n  /* ... */\n};\nMyComponent.defaultProps = {\n  /* ... */\n};\n\nconst MyObserver = observerWrap(MyComponent);\n\nMyObserver.defaultHooks = {\n  ...MyComponent.defaultHooks, // copy original\n  onComponentShouldUpdate: (prev, next) => {\n    /* ... */\n  },\n};\n```\n\n## Legacy Example\n\nYou can inject props using the following syntax ( This example requires, babel decorators-legacy plugin )\n\n```javascript\n// MyComponent.js\nimport { Component } from 'inferno';\nimport { inject, observer } from 'inferno-mobx';\n\n@inject('englishStore', 'frenchStore')\n@observer\nclass MyComponent extends Component {\n  render({ englishStore, frenchStore }) {\n    return (\n      <div>\n        <p>{englishStore.title}</p>\n        <p>{frenchStore.title}</p>\n      </div>\n    );\n  }\n}\n\nexport default MyComponent;\n```\n\nIf you're not using decorators, you can do this instead:\n\n```javascript\n// MyComponent.js\nimport { Component } from 'inferno';\nimport { inject, observer } from 'inferno-mobx';\n\nclass MyComponent extends Component {\n  render({ englishStore, frenchStore }) {\n    return (\n      <div>\n        <p>{englishStore.title}</p>\n        <p>{frenchStore.title}</p>\n      </div>\n    );\n  }\n}\n\nexport default inject('englishStore', 'frenchStore')(observer(MyComponent));\n```\n\nJust make sure that you provided your stores using the `Provider`. Ex:\n\n```javascript\n// index.js\nimport { render } from 'inferno';\nimport { Provider } from 'inferno-mobx';\nimport { observable } from 'mobx';\nimport MyComponent from './MyComponent';\n\nconst englishStore = observable({\n  title: 'Hello World',\n});\n\nconst frenchStore = observable({\n  title: 'Bonjour tout le monde',\n});\n\nrender(\n  <Provider englishStore={englishStore} frenchStore={frenchStore}>\n    <MyComponent />\n  </Provider>,\n  document.getElementById('root'),\n);\n```\n\n## Migrating from observer to observerPatch\n\nThe `observerPatch` was added because the way `observer` was implemented cannot work on class Components that implement either `getSnapshotBeforeUpdate` or `getDerivedStateFromProps`.\nHaving differences in implementation that can matter to user code based on which lifecycle hooks are present is not good design.\nChanging how `observer` is implemented in ways that could break existing user code is not worth the cost.\nFurthermore, `observerPatch` provides better performance in the resulting class than `observer`.\n\nThe differences to be aware of when switching from `observer` to `observerPatch` are:\n\n1. `observerPatch` is not implemented to be used as a decorator\n2. `observerPatch` returns `void` instead of returning the class it was applied to\n3. `observerPatch` will not have the observer call `this.componentWillReact()` if such a member exists\n4. `observerPatch` does not add a `shouldComponentUpdate` hook to classes that do not have one\n5. `observerPatch` will not forward exceptions thrown by `render` to `errorsReporter`\n6. `observerPatch` ignores `useStaticRendering(true)`\n7. `observerPatch` will not emit events through `renderReporter` that list how long `render` took\n8. `observerPatch` does not make `this.props` nor `this.state` observable\n9. `observerPatch` does not set `isMobXReactObserver = true` as a static class member\n10. `observerWrap` returns a functional Component, where `observer` returns a class Component.\n\nPoints 1 and 2 are a simple change to call `observerPatch` after the class is defined and removing `observer`.\n\nTo replicate the behavior of `observer` for point 3, call `this.componentWillReact()` at the start of your `componentWillMount` hook.\nOr if your Component does not have a `componentWillMount`, rename `componentWillReact` to `componentWillMount`.\n\nFor point 4, you can implement your own `shouldComponentUpdate` hook is you want to prevent needless re-renders.\nThe `shouldComponentUpdate` does not affect re-renders triggered by MobX obervables being modified.\nSo it exists for when new properties are set or `this.setState` is used.\n\nFor point 5, you can intercept the exceptions in your render method and send them to a handler if desired.\n\nFor point 6, all your components other than those passed to `observer` already ignore it.\nIf there is demand, generating warning messages might return `useStaticRendering(true)` is called.\nBut it would only be in development builds of Inferno and would not prevent methods from running.\n\nFor point 7, you can do it better that `observer` did.\nAlso, it only did so if you toggled it on by calling `trackComponents()`.\n\nPoint 8 means that if you directly set `this.props` or `this.state` to a new value it will not trigget a re-render.\nYou should not be directly setting `this.props`. Let Inferno update Component properties.\nYou should not be directly setting `this.state` outside of the `componentWillMount` and `componentWillReceiveProps` hooks.\nThe component will always have `render` called after `componentWillMount`.\nThe component will have `render` called after `componentWillReceiveProps` unless `shouldComponentUpdate` returns `false`.\nAny time Inferno updates `this.props` or `this.setState` is used to update state, the component will re-render unless `shouldComponentUpdate` returns `false`.\n\nFor point 9, `observerPatch` instead sets `isMobXInfernoObserver = true` as a static member of the class.\nBut it only does do in development builds as it is intended for use internally for sanity checks.\nThe issues it is used to spot and warn about should be fixed before reaching production.\n\nFinally for point 10, if you specify the Component VNode type to optimize renders, you will need to change the flags.\n\nIf this seems intimidating, know that nearly all unit tests for `observer` worked as they were after replacing `observer` with `observerPatch`.\nOutside of needing to switch functional Components to class Components, that is.\n\n## Using observerPatch with Provider and inject\n\nThe `observerPatch` function can be used with `Provider` and `inject` just like with `observer`.\nHowever, using `inject` as a decorator along side `observerPatch` is not supported.\n\n```tsx\n// MyInjected.tsx\nimport { Component } from 'inferno';\nimport { observerPatch, observerWrap, inject } from 'inferno-mobx';\n\ninterface CountStore {\n  readonly count: number;\n}\n\n// The class produced by inject will require the injected properties if required by the base class\nclass MyComponentA extends Component<{ countStore?: CountStore }> {\n  render({ countStore }: { countStore?: CountStore }) {\n    // If only the injected version will be used, casting is safe as an exception is thrown\n    // if the property is unavailable\n    const count = (countStore as CountStore).count.toString(); // unsafe if MyComponentA was exported\n    return <p>Current Count: {count}</p>;\n  }\n}\n\n// Recommended order\nobserverPatch(MyComponentA);\nexport const MyInjectedA = inject('countStore')(MyComponentA);\n\nclass MyComponentB extends Component<{ countStore?: CountStore }> {\n  render({ countStore }: { countStore?: CountStore }) {\n    const count = (countStore as CountStore).count.toString();\n    return <p>Current Count: {count}</p>;\n  }\n}\n\n// The order of inject and observerPatch does not matter.\nexport const MyInjectedB = inject('countStore')(MyComponentB);\nobserverPatch(MyComponentB); // Works, but this order is more prone to the mistake shown below\n\nclass MyComponentC extends Component<{ countStore?: CountStore }> {\n  render({ countStore }: { countStore?: CountStore }) {\n    const count = (countStore as CountStore).count.toString();\n    return <p>Current Count: {count}</p>;\n  }\n}\n\n// Be sure to use observerPatch on the class, not the injected class.\n// A warning message is output if you do this.\nexport const MyInjectedC = inject('countStore')(MyComponentC);\nobserverPatch(MyInjectedC); // WRONG! Should be: observerPatch(MyComponentC);\n//Having observerPatch before inject lets tools detect this issue.\n\n// Functional components with observerWrap\nfunction MyComponentD({ countStore }: { countStore?: CountStore }) {\n  const count = (countStore as CountStore).count.toString();\n  return <p>Current Count: {count}</p>;\n}\nexport const MyInjectedD = inject(observerWrap(MyComponentD));\n```\n\n```tsx\n// index.tsx\nimport {\n  MyInjectedA,\n  MyInjectedB,\n  MyInjectedC,\n  MyInjectedD,\n} from './MyInjected';\nimport { render } from 'inferno';\nimport { Provider } from 'inferno-mobx';\nimport { action, observable } from 'mobx';\n\nconst store = observable({ count: 0 });\n\nconst store2 = observable({ count: 0 });\n\n// NOTE: Do not use Provider and inject for trivial cases like this in real code.\nrender(\n  <div>\n    <Provider countStore={store}>\n      <MyInjectedA />\n      <MyInjectedB />\n      <MyInjectedC />{' '}\n      {/* This one will not update as MyComponentC was not made into an observer. */}\n      <MyInjectedD />\n      <MyInjectedA countStore={store2} />{' '}\n      {/* Will not update as direct properties override injection */}\n    </Provider>\n    <button\n      type=\"button\"\n      onClick={action(() => {\n        store.count += 1;\n      })}\n    >\n      Click Me\n    </button>\n  </div>,\n  document.getElementById('root'),\n);\n```\n\nIMPORTANT: The values injected are the ones available to `Provider` when it is first mounted.\nSo `Provider` and `inject` are only useful for properties that will NEVER change.\n\n## Server Side Rendering and Hydration\n\nWhen rendering server side, components only need to be rendered once and does not update.\nThis means you do not need your components to act as observers when running on the server.\n\nFurthermore, the functions provided by inferno-server initialize components but does not call their unmount hooks.\nWhich for observers means their internal MobX reactions are not disposed.\n\nSo for your server code components should not act as observers.\n\nThe best way to achieve this is to have calls to `observer` and `observerPatch` be conditional and not called server side.\n\n```tsx\n// MyComponent.tsx\nimport { Component } from 'inferno';\nimport { observerPatch, observerWrap } from 'inferno-mobx';\n\ninterface CountStore {\n  readonly count: number;\n}\n\nexport class MyComponent extends Component<{ countStore: CountStore }> {\n  render({ countStore }: { countStore: CountStore }) {\n    return <p>Current Count: {countStore.count.toString()}</p>;\n  }\n}\n\nfunction MyFunctional({ countStore }: { countStore: CountStore }) {\n  return <p>Current Count: {countStore.count.toString()}</p>;\n}\n\n// You do not have to use an environment variable nor is the specific one used important.\n// The idea would be to replace 'process.env.SERVER_SIDE' with a literal true or false.\n// This can be done when transpiling with Babel or many bundling tools have plugins that can do so.\n// Then a good minifier such a terser can elimitate the if statement for production.\nif (process.env.SERVER_SIDE !== true) {\n  observerPatch(MyComponent); // The same goes can be done for 'observer' calls.\n}\n\n// For functional components\nconst MyObserver =\n  process.env.SERVER_SIDE !== true ? observerWrap(MyFunctional) : MyFunctional;\nexport { MyObserver as MyFunctional };\n```\n\nThen you can use `renderToString` and `hydrate` as you would with any other component.\n\nIf you use `observer` instead of `observerPatch` you can alternatively call `useStaticRendering(true)` in your server code.\nThe `useStaticRendering` function is exported by inferno-mobx and only needs to be called once before any rendering occurs.\nWhen called with `true`, it will make the components `observer` skip the code that turns them into observers.\nHowever, simply not calling `observer` server side will yield better performance.\n\nIf you use `inject` to supply properties in you render code, you still need to call it on the server side.\n\nWhen a custom function to get stores is passed to `inject`, it internally calls `observer` on the created class.\nAs such if you are using a custom function to get stores for `inject` you need to call `useStaticRendering(true)` in your server side code.\n"
  },
  {
    "path": "packages/inferno-mobx/__tests__/context.spec.jsx",
    "content": "import { render, Component } from 'inferno';\nimport { observer, Provider } from 'inferno-mobx';\nimport { observable } from 'mobx';\n\ndescribe('observer based context', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('using observer to inject throws warning', (done) => {\n    const w = console.error;\n    const warns = [];\n    console.error = (msg) => warns.push(msg);\n\n    observer(['test'], () => null);\n\n    expect(warns.length).toBe(1);\n    expect(warns[0]).toEqual(\n      'Mobx observer: Using observer to inject stores is deprecated since 4.0. Use `@inject(\"store1\", \"store2\") @observer ComponentClass` or `inject(\"store1\", \"store2\")(observer(componentClass))` instead of `@observer([\"store1\", \"store2\"]) ComponentClass`',\n    );\n\n    console.error = w;\n    done();\n  });\n\n  it('basic context', (done) => {\n    const C = observer(\n      ['foo'],\n      class Foo extends Component {\n        render() {\n          return (\n            <div>\n              context:\n              {this.props.foo}\n            </div>\n          );\n        }\n      },\n    );\n    const B = () => <C />;\n    const A = () => (\n      <Provider foo=\"bar\">\n        <B />\n      </Provider>\n    );\n    render(<A />, container);\n    expect(container.querySelector('div').textContent).toBe('context:bar');\n\n    done();\n  });\n\n  it('props override context', (done) => {\n    const C = observer(\n      ['foo'],\n      class Foo extends Component {\n        render() {\n          return (\n            <div>\n              context:\n              {this.props.foo}\n            </div>\n          );\n        }\n      },\n    );\n    const B = () => <C foo={42} />;\n    const A = () => (\n      <Provider foo=\"bar\">\n        <B />\n      </Provider>\n    );\n    render(<A />, container);\n    expect(container.querySelector('div').textContent).toBe('context:42');\n    done();\n  });\n\n  it('overriding stores is supported', (done) => {\n    const C = observer(\n      ['foo', 'bar'],\n      class Foobar extends Component {\n        render() {\n          return (\n            <div>\n              context:\n              {this.props.foo}\n              {this.props.bar}\n            </div>\n          );\n        }\n      },\n    );\n    const B = () => <C />;\n    const A = () => (\n      <Provider foo=\"bar\" bar={1337}>\n        <div>\n          <span>\n            <B />\n          </span>\n          <section>\n            <Provider foo={42}>\n              <B />\n            </Provider>\n          </section>\n        </div>\n      </Provider>\n    );\n    render(<A />, container);\n\n    expect(container.querySelector('span').textContent).toBe('context:bar1337');\n    expect(container.querySelector('section').textContent).toBe(\n      'context:421337',\n    );\n    done();\n  });\n\n  it('store should be available', (done) => {\n    const C = observer(\n      ['foo'],\n      class Foo extends Component {\n        render() {\n          return (\n            <div>\n              context:\n              {this.props.foo}\n            </div>\n          );\n        }\n      },\n    );\n    const B = () => <C />;\n    const A = () => (\n      <Provider baz={42}>\n        <B />\n      </Provider>\n    );\n    try {\n      render(<A />, container);\n    } catch (e) {\n      expect(e.message).toBe(\n        \"MobX injector: Store 'foo' is not available! Make sure it is provided by some Provider\",\n      );\n      done();\n    }\n  });\n\n  it('store is not required if prop is available', (done) => {\n    const C = observer(\n      ['foo'],\n      class extends Component {\n        render() {\n          return (\n            <div>\n              context:\n              {this.props.foo}\n            </div>\n          );\n        }\n      },\n    );\n    const B = () => <C foo=\"bar\" />;\n    render(<B />, container);\n    expect(container.querySelector('div').textContent).toBe('context:bar');\n    done();\n  });\n\n  it('warning is printed when changing stores', (done) => {\n    let msg = null;\n    const baseWarn = console.error;\n    console.error = (m) => (msg = m);\n    const a = observable.box(3);\n    const C = observer(\n      ['foo'],\n      class extends Component {\n        render() {\n          return (\n            <div>\n              context:\n              {this.props.foo}\n            </div>\n          );\n        }\n      },\n    );\n    const B = observer(\n      class extends Component {\n        render() {\n          return <C />;\n        }\n      },\n    );\n    const A = observer(\n      class extends Component {\n        render() {\n          return (\n            <section>\n              <span>{a.get()}</span>,\n              <Provider foo={a.get()}>\n                <B />\n              </Provider>\n            </section>\n          );\n        }\n      },\n    );\n    render(<A />, container);\n    expect(container.querySelector('span').textContent).toBe('3');\n    expect(container.querySelector('div').textContent).toBe('context:3');\n    a.set(42);\n    expect(container.querySelector('span').textContent).toBe('42');\n    expect(container.querySelector('div').textContent).toBe('context:3');\n    expect(msg).toEqual(\n      \"MobX Provider: Provided store 'foo' has changed. Please avoid replacing stores as the change might not propagate to all children\",\n    );\n    console.error = baseWarn;\n    done();\n  });\n\n  it('warning is not printed when changing stores, but suppressed explicitly', (done) => {\n    let msg = null;\n    const baseWarn = console.error;\n    console.error = (m) => (msg = m);\n    const a = observable.box(3);\n    const C = observer(\n      ['foo'],\n      class extends Component {\n        render() {\n          return (\n            <div>\n              context:\n              {this.props.foo}\n            </div>\n          );\n        }\n      },\n    );\n    const B = observer(\n      class extends Component {\n        render() {\n          return <C />;\n        }\n      },\n    );\n    const A = observer(\n      class extends Component {\n        render() {\n          return (\n            <section>\n              <span>{a.get()}</span>,\n              <Provider foo={a.get()} suppressChangedStoreWarning>\n                <B />\n              </Provider>\n            </section>\n          );\n        }\n      },\n    );\n    render(<A />, container);\n    expect(container.querySelector('span').textContent).toBe('3');\n    expect(container.querySelector('div').textContent).toBe('context:3');\n    a.set(42);\n    expect(container.querySelector('span').textContent).toBe('42');\n    expect(container.querySelector('div').textContent).toBe('context:3');\n    expect(msg).toBe(null);\n    console.error = baseWarn;\n    done();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-mobx/__tests__/extra/eventemitter.spec.js",
    "content": "import { EventEmitter } from 'inferno-mobx';\n\ndescribe('EventEmitter', () => {\n  it('Should be possible to listen changes and remove listeners by calling callback', () => {\n    const emitter = new EventEmitter();\n    const listener1 = function () {};\n    expect(emitter.listeners.length).toEqual(0);\n\n    const listener = emitter.on(listener1);\n\n    expect(emitter.listeners.length).toEqual(1);\n    expect(emitter.listeners[0]).toEqual(listener1);\n\n    listener();\n\n    expect(emitter.listeners.length).toEqual(0);\n  });\n\n  it('Should do nothing if removing same callback twice/or more', () => {\n    const emitter = new EventEmitter();\n    const listener1 = function () {};\n    expect(emitter.listeners.length).toEqual(0);\n\n    const listener = emitter.on(listener1);\n\n    expect(emitter.listeners.length).toEqual(1);\n    expect(emitter.listeners[0]).toEqual(listener1);\n\n    listener();\n    listener();\n    listener();\n\n    expect(emitter.listeners.length).toEqual(0);\n  });\n\n  it('Should emit the change data to all active listeners', () => {\n    const emitter = new EventEmitter();\n    const listener1 = function () {};\n    const listener2 = function (data) {\n      console.error(data);\n    };\n\n    spyOn(console, 'error');\n\n    expect(emitter.listeners.length).toEqual(0);\n\n    const listener = emitter.on(listener1);\n    emitter.on(listener2);\n\n    expect(emitter.listeners.length).toEqual(2);\n    expect(emitter.listeners[0]).toEqual(listener1);\n\n    listener();\n    listener();\n    listener();\n\n    expect(emitter.listeners.length).toEqual(1);\n\n    emitter.emit('foobar');\n\n    expect(console.error.calls.count()).toBe(1);\n    expect(console.error.calls.argsFor(0)[0]).toContain('foobar');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-mobx/__tests__/generic.spec.jsx",
    "content": "import { Component, render } from 'inferno';\nimport { observer, Provider } from 'inferno-mobx';\n\ndescribe('generic higher order components', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('injects and observes', (done) => {\n    /** @type {<T>(x: T | null | undefined) => T} */\n    const nullthrows = (/** @type {any} */ x) => {\n      if (!x) {\n        throw new Error('Unexpected falsy value.');\n      }\n\n      return x;\n    };\n\n    class ApiService {\n      constructor() {\n        this.foo = 'bar';\n      }\n    }\n\n    class TodoService {\n      constructor() {\n        this.baz = 'qux';\n      }\n    }\n\n    /**\n     * @typedef IProps\n     * @property {ApiService?} [apiService]\n     * @property {TodoService?} [todoService]\n     *\n     * @extends Component<IProps>\n     */\n    class TodoView extends Component {\n      render() {\n        const { foo } = nullthrows(this.props.apiService);\n        const { baz } = nullthrows(this.props.todoService);\n\n        return (\n          <p>\n            {foo}\n            {baz}\n          </p>\n        );\n      }\n    }\n\n    const Todo = observer(['apiService', 'todoService'], TodoView);\n\n    const services = {\n      apiService: new ApiService(),\n      todoService: new TodoService(),\n    };\n\n    const A = () => (\n      <Provider {...services}>\n        <Todo />\n      </Provider>\n    );\n\n    render(<A />, container);\n    expect(container.querySelector('p').textContent).toBe('barqux');\n\n    done();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-mobx/__tests__/inject.spec.jsx",
    "content": "import { render, Component } from 'inferno';\nimport { inject, observer, Provider } from 'inferno-mobx';\nimport { observable } from 'mobx';\n\ndescribe('inject based context', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('basic context', (done) => {\n    const C = inject('foo')(\n      observer(\n        class Foo extends Component {\n          render() {\n            return (\n              <div>\n                context:\n                {this.props.foo}\n              </div>\n            );\n          }\n        },\n      ),\n    );\n    const B = () => <C />;\n    const A = () => (\n      <Provider foo=\"bar\">\n        <B />\n      </Provider>\n    );\n    render(<A />, container);\n    expect(container.querySelector('div').textContent).toBe('context:bar');\n    done();\n  });\n\n  it('props override context', (done) => {\n    const C = inject('foo')(\n      class extends Component {\n        render() {\n          return (\n            <div>\n              context:\n              {this.props.foo}\n            </div>\n          );\n        }\n      },\n    );\n    const B = () => <C foo={42} />;\n    class A extends Component {\n      render() {\n        return (\n          <Provider foo=\"bar\">\n            <B />\n          </Provider>\n        );\n      }\n    }\n    render(<A />, container);\n    expect(container.querySelector('div').textContent).toBe('context:42');\n    done();\n  });\n\n  it('overriding stores is supported', (done) => {\n    const C = inject(\n      'foo',\n      'bar',\n    )(\n      observer(\n        class extends Component {\n          render() {\n            return (\n              <div>\n                context:\n                {this.props.foo}\n                {this.props.bar}\n              </div>\n            );\n          }\n        },\n      ),\n    );\n    const B = () => <C />;\n    class A extends Component {\n      render() {\n        return (\n          <Provider foo=\"bar\" bar={1337}>\n            <div>\n              <span>\n                <B />\n              </span>\n              <section>\n                <Provider foo={42}>\n                  <B />\n                </Provider>\n              </section>\n            </div>\n          </Provider>\n        );\n      }\n    }\n\n    render(<A />, container);\n    expect(container.querySelector('span').textContent).toBe('context:bar1337');\n    expect(container.querySelector('section').textContent).toBe(\n      'context:421337',\n    );\n    done();\n  });\n\n  it('store should be available', (done) => {\n    const C = inject('foo')(\n      observer(\n        class extends Component {\n          render() {\n            return (\n              <div>\n                context:\n                {this.props.foo}\n              </div>\n            );\n          }\n        },\n      ),\n    );\n    const B = () => <C />;\n    class A extends Component {\n      render() {\n        return (\n          <Provider baz={42}>\n            <B />\n          </Provider>\n        );\n      }\n    }\n\n    try {\n      render(<A />, container);\n    } catch (e) {\n      expect(e.message).toBe(\n        \"MobX injector: Store 'foo' is not available! Make sure it is provided by some Provider\",\n      );\n      done();\n    }\n  });\n\n  it('store is not required if prop is available', (done) => {\n    const C = inject('foo')(\n      observer(\n        class extends Component {\n          render() {\n            return (\n              <div>\n                context:\n                {this.props.foo}\n              </div>\n            );\n          }\n        },\n      ),\n    );\n    const B = () => <C foo=\"bar\" />;\n    render(<B />, container);\n    expect(container.querySelector('div').textContent).toBe('context:bar');\n    done();\n  });\n\n  it('inject merges (and overrides) props', (done) => {\n    const C = inject(() => ({ a: 1 }))(\n      observer(\n        class extends Component {\n          render() {\n            expect(this.props).toEqual({ a: 1, b: 2 });\n            return null;\n          }\n        },\n      ),\n    );\n    const B = () => <C a={2} b={2} />;\n    render(<B />, container);\n    done();\n  });\n\n  it('warning is printed when changing stores', (done) => {\n    let msg;\n    const baseWarn = console.error;\n    console.error = (m) => (msg = m);\n    const a = observable.box(3);\n    const C = observer(\n      ['foo'],\n      class extends Component {\n        render() {\n          return (\n            <div>\n              context:\n              {this.props.foo}\n            </div>\n          );\n        }\n      },\n    );\n    const B = observer(\n      class extends Component {\n        render() {\n          return <C />;\n        }\n      },\n    );\n    const A = observer(\n      class extends Component {\n        render() {\n          return (\n            <section>\n              <span>{a.get()}</span>\n              <Provider foo={a.get()}>\n                <B />\n              </Provider>\n            </section>\n          );\n        }\n      },\n    );\n    render(<A />, container);\n\n    expect(container.querySelector('span').textContent).toBe('3');\n    expect(container.querySelector('div').textContent).toBe('context:3');\n\n    a.set(42);\n\n    expect(container.querySelector('span').textContent).toBe('42');\n    expect(container.querySelector('div').textContent).toBe('context:3');\n\n    expect(msg).toBe(\n      \"MobX Provider: Provided store 'foo' has changed. Please avoid replacing stores as the change might not propagate to all children\",\n    );\n    console.error = baseWarn;\n    done();\n  });\n\n  it('custom storesToProps', (done) => {\n    const C = inject((stores, props, context) => {\n      expect(context).toEqual({ mobxStores: { foo: 'bar' } });\n      expect(stores).toEqual({ foo: 'bar' });\n      expect(props).toEqual({ baz: 42 });\n\n      return {\n        zoom: stores.foo,\n        baz: props.baz * 2,\n      };\n    })(\n      observer(\n        class extends Component {\n          render() {\n            return (\n              <div>\n                context:\n                {this.props.zoom}\n                {this.props.baz}\n              </div>\n            );\n          }\n        },\n      ),\n    );\n    class B extends Component {\n      render() {\n        return <C baz={42} />;\n      }\n    }\n\n    const A = () => (\n      <Provider foo=\"bar\">\n        <B />\n      </Provider>\n    );\n    render(<A />, container);\n    expect(container.querySelector('div').textContent).toBe('context:bar84');\n    done();\n  });\n\n  it('support static hoisting, wrappedComponent and wrappedInstance', (done) => {\n    class B extends Component {\n      render() {\n        this.testField = 1;\n        return <div>{this.testField}</div>;\n      }\n    }\n\n    B.bla = 17;\n    B.bla2 = {};\n    const C = inject('booh')(B);\n\n    expect(C.wrappedComponent).toBe(B);\n    expect(B.bla).toBe(17);\n    expect(C.bla).toBe(17);\n\n    let c = null;\n    render(<C ref={(i) => (c = i)} booh={42} />, container);\n    expect(c.wrappedInstance.testField).toBe(1);\n    done();\n  });\n\n  // DefaultProps only, there are no propTypes in inferno\n  it('propTypes and defaultProps are forwarded', (done) => {\n    const msg = [];\n    const baseError = console.error;\n    console.error = (m) => msg.push(m);\n\n    const C = inject('foo')(\n      class extends Component {\n        static displayName = 'C';\n        render() {\n          expect(this.props.y).toBe(3);\n          return null;\n        }\n      },\n    );\n    C.defaultProps = {\n      y: 3,\n    };\n    const B = () => <C z=\"test\" />;\n    const A = () => (\n      <Provider foo=\"bar\">\n        <B />\n      </Provider>\n    );\n    render(<A />, container);\n    expect(msg.length).toBe(0);\n    console.error = baseError;\n    done();\n  });\n\n  it('using a custom injector is reactive', (done) => {\n    const user = observable({ name: 'Noa' });\n    const mapper = (stores) => ({ name: stores.user.name });\n    const DisplayName = (props) => <h1>{props.name}</h1>;\n    const User = inject(mapper)(DisplayName);\n    const App = () => (\n      <Provider user={user}>\n        <User />\n      </Provider>\n    );\n    render(<App />, container);\n\n    expect(container.querySelector('h1').textContent).toBe('Noa');\n\n    user.name = 'Veria';\n    expect(container.querySelector('h1').textContent).toBe('Veria');\n    done();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-mobx/__tests__/misc.spec.jsx",
    "content": "import { render, rerender, Component } from 'inferno';\nimport { observer } from 'inferno-mobx';\nimport { extendObservable, observable } from 'mobx';\n\ndescribe('Mobx Misc', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('custom shouldComponentUpdate is not respected for observable changes (#50)', (done) => {\n    let called = 0;\n    const x = observable.box(3);\n    const C = observer(\n      class Foo extends Component {\n        render() {\n          return (\n            <div>\n              value:\n              {x.get()}\n            </div>\n          );\n        }\n\n        shouldComponentUpdate() {\n          called++;\n\n          return false;\n        }\n      },\n    );\n    render(<C />, container);\n    expect(container.querySelector('div').textContent).toBe('value:3');\n    expect(called).toBe(0);\n    x.set(42);\n    expect(container.querySelector('div').textContent).toBe('value:42');\n    expect(called).toBe(0);\n    done();\n  });\n\n  it('custom shouldComponentUpdate is not respected for observable changes (#50) - 2', (done) => {\n    let called = 0;\n    const y = observable.box(5);\n    const C = observer(\n      class Foo extends Component {\n        render() {\n          return (\n            <div>\n              value:\n              {this.props.y}\n            </div>\n          );\n        }\n\n        shouldComponentUpdate(nextProps) {\n          called++;\n          return nextProps.y !== 42;\n        }\n      },\n    );\n    const B = observer(\n      class Foo extends Component {\n        render() {\n          return (\n            <span>\n              <C y={y.get()} />\n            </span>\n          );\n        }\n      },\n    );\n    render(<B />, container);\n    expect(container.querySelector('div').textContent).toBe('value:5');\n    expect(called).toBe(0);\n\n    y.set(6);\n    expect(container.querySelector('div').textContent).toBe('value:6');\n    expect(called).toBe(1);\n\n    y.set(42); // SCU => False\n    expect(container.querySelector('div').textContent).toBe('value:42');\n    expect(called).toBe(2);\n\n    y.set(7);\n    expect(container.querySelector('div').textContent).toBe('value:7');\n    expect(called).toBe(3);\n\n    done();\n  });\n\n  it('issue mobx 405', (done) => {\n    function ExampleState() {\n      extendObservable(this, {\n        name: 'test',\n        get greetings() {\n          return 'Hello my name is ' + this.name;\n        },\n      });\n    }\n\n    const ExampleView = observer(\n      class Foo extends Component {\n        render() {\n          return (\n            <div>\n              <input\n                type=\"text\"\n                onChange={(e) =>\n                  (this.props.exampleState.name = e.target.value)\n                }\n                value={this.props.exampleState.name}\n              />\n              <span>{this.props.exampleState.greetings}</span>\n            </div>\n          );\n        }\n      },\n    );\n\n    const exampleState = new ExampleState();\n    render(<ExampleView exampleState={exampleState} />, container);\n    expect(container.querySelector('span').textContent).toBe(\n      'Hello my name is test',\n    );\n\n    done();\n  });\n\n  it('#85 Should handle state changing in constructors', function () {\n    const a = observable.box(2);\n    const Child = observer(\n      class Foo extends Component {\n        displayName = 'Child';\n        constructor(props) {\n          super(props);\n          a.set(3);\n          this.state = {};\n        }\n\n        render() {\n          return (\n            <div>\n              child:\n              {a.get()} -{' '}\n            </div>\n          );\n        }\n      },\n    );\n    const ParentWrapper = observer(function Parent() {\n      return (\n        <span>\n          <Child />\n          parent:\n          {a.get()}\n        </span>\n      );\n    });\n    render(<ParentWrapper />, container);\n\n    expect(container.getElementsByTagName('span')[0].textContent).toBe(\n      'child:3 - parent:2',\n    );\n    a.set(5);\n\n    rerender();\n\n    expect(container.getElementsByTagName('span')[0].textContent).toBe(\n      'child:5 - parent:5',\n    );\n    a.set(7);\n\n    rerender();\n\n    expect(container.getElementsByTagName('span')[0].textContent).toBe(\n      'child:7 - parent:7',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-mobx/__tests__/observer.spec.jsx",
    "content": "import { Component, render } from 'inferno';\nimport {\n  extendObservable,\n  getObserverTree,\n  observable,\n  runInAction,\n} from 'mobx';\nimport {\n  inject,\n  observer,\n  Observer,\n  onError,\n  trackComponents,\n  useStaticRendering,\n} from 'inferno-mobx';\n\nconst store = observable({\n  todos: [\n    {\n      title: 'a',\n      completed: false,\n    },\n  ],\n});\n\nlet todoItemRenderings = 0;\nconst TodoItem = observer(function TodoItem(props) {\n  todoItemRenderings++;\n  return <li>|{props.todo.title}</li>;\n});\n\nlet todoListRenderings = 0;\nlet todoListWillReactCount = 0;\nconst TodoList = observer(\n  class extends Component {\n    componentWillReact() {\n      todoListWillReactCount++;\n    }\n\n    render() {\n      todoListRenderings++;\n      const todos = store.todos;\n      return (\n        <div>\n          <hi>{todos.length}</hi>\n          {todos.map((todo, idx) => (\n            <TodoItem key={idx} todo={todo} />\n          ))}\n        </div>\n      );\n    }\n  },\n);\n\nconst App = () => <TodoList />;\n\ndescribe('Mobx Observer', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  beforeAll(function () {\n    trackComponents();\n  });\n\n  it('nestedRendering', () => {\n    render(<App />, container);\n    expect(todoListRenderings).toEqual(1); //, 'should have rendered list once');\n    expect(todoListWillReactCount).toEqual(0); //, 'should not have reacted yet')\n    expect(container.querySelectorAll('li').length).toEqual(1);\n    expect(container.querySelector('li').textContent).toEqual('|a');\n\n    expect(todoItemRenderings).toEqual(1); // 'item1 should render once'\n\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1);\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1);\n\n    store.todos[0].title += 'a';\n\n    expect(todoListRenderings).toEqual(1); //, 'should have rendered list once');\n    expect(todoListWillReactCount).toEqual(0); //, 'should not have reacted')\n    expect(todoItemRenderings).toEqual(2); //, 'item1 should have rendered twice');\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1); //, 'observers count shouldn\\'t change');\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1); //, 'title observers should not have increased');\n\n    store.todos.push({\n      title: 'b',\n      completed: true,\n    });\n\n    expect(container.querySelectorAll('li').length).toBe(2); //, 'list should two items in the list');\n    const expectedOutput = [];\n    const nodes = container.querySelectorAll('li');\n\n    for (let i = 0; i < nodes.length; i++) {\n      expectedOutput.push(nodes[i].textContent);\n    }\n    expect(expectedOutput).toEqual(['|aa', '|b']);\n\n    expect(todoListRenderings).toBe(2); // 'should have rendered list twice');\n    expect(todoListWillReactCount).toBe(1); //, 'should have reacted')\n    expect(todoItemRenderings).toBe(3); //, 'item2 should have rendered as well');\n    expect(getObserverTree(store.todos[1], 'title').observers.length).toBe(1); //, 'title observers should have increased');\n    expect(\n      getObserverTree(store.todos[1], 'completed').observers,\n    ).not.toBeDefined(); //, 'completed observers should not have increased');\n\n    const oldTodo = store.todos.pop();\n\n    expect(todoListRenderings).toBe(3); //, 'should have rendered list another time');\n    expect(todoListWillReactCount).toBe(2); //, 'should have reacted')\n    expect(todoItemRenderings).toBe(3); //, 'item1 should not have rerendered');\n    expect(container.querySelectorAll('li').length).toBe(1); //, 'list should have only on item in list now');\n    expect(getObserverTree(oldTodo, 'title').observers).not.toBeDefined(); //, 'title observers should have decreased');\n    expect(getObserverTree(oldTodo, 'completed').observers).not.toBeDefined(); //, 'completed observers should not have decreased');\n  });\n\n  it('keep views alive', () => {\n    let yCalcCount = 0;\n    const data = observable({\n      x: 3,\n      get y() {\n        yCalcCount++;\n        return this.x * 2;\n      },\n      z: 'hi',\n    });\n\n    const TestComponent = observer(function testComponent() {\n      return (\n        <div>\n          {data.z}\n          {data.y}\n        </div>\n      );\n    });\n\n    render(<TestComponent />, container);\n    expect(yCalcCount).toBe(1);\n    expect(container.textContent).toBe('hi6');\n\n    data.z = 'hello';\n    // test: rerender should not need a recomputation of data.y because the subscription is kept alive\n\n    expect(yCalcCount).toBe(1);\n\n    expect(container.textContent).toBe('hello6');\n    expect(yCalcCount).toBe(1);\n\n    expect(getObserverTree(data, 'y').observers.length).toBe(1);\n\n    render(<div />, container);\n\n    expect(getObserverTree(data, 'y').observers).not.toBeDefined();\n  });\n\n  it('componentWillMount from mixin is run first', (done) => {\n    let origRenderMethod;\n    class clss extends Component {\n      componentWillMount() {\n        // ugly check, but proofs that observer.willmount has run\n        // We cannot use function.prototype.name here like in react-redux tests because it is not supported in Edge/IE\n        expect(this.render).not.toBe(origRenderMethod);\n      }\n\n      render() {\n        return null;\n      }\n    }\n\n    origRenderMethod = clss.prototype.render;\n\n    const Comp = observer(clss);\n    render(<Comp />, container);\n    done();\n  });\n\n  it('does not views alive when using static rendering', () => {\n    useStaticRendering(true);\n\n    let renderCount = 0;\n    const data = observable({\n      z: 'hi',\n    });\n\n    const TestComponent = observer(function testComponent() {\n      renderCount++;\n      return <div>{data.z}</div>;\n    });\n\n    render(<TestComponent />, container);\n\n    expect(renderCount).toBe(1);\n    expect(container.querySelector('div').textContent).toBe('hi');\n\n    data.z = 'hello';\n    // no re-rendering on static rendering\n\n    expect(renderCount).toBe(1);\n\n    expect(container.querySelector('div').textContent).toBe('hi');\n    expect(renderCount).toBe(1);\n\n    expect(getObserverTree(data, 'z').observers).not.toBeDefined();\n\n    useStaticRendering(false);\n  });\n\n  it('issue 12', function () {\n    const data = observable({\n      selected: 'coffee',\n      items: [\n        {\n          name: 'coffee',\n        },\n        {\n          name: 'tea',\n        },\n      ],\n    });\n\n    /** Row Class */\n    class Row extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return (\n          <span>\n            {this.props.item.name}\n            {data.selected === this.props.item.name ? '!' : ''}\n          </span>\n        );\n      }\n    }\n\n    /** table stateles component */\n    const Table = observer(function table() {\n      return (\n        <div>\n          {data.items.map((item) => (\n            <Row key={item.name} item={item} />\n          ))}\n        </div>\n      );\n    });\n\n    render(<Table />, container);\n\n    expect(container.querySelector('div').textContent).toBe('coffee!tea');\n\n    runInAction(() => {\n      data.items[1].name = 'boe';\n      data.items.splice(0, 2, { name: 'soup' });\n      data.selected = 'tea';\n    });\n\n    expect(container.querySelector('div').textContent).toBe('soup');\n  });\n\n  it('component should not be inject', function (done) {\n    const msg = [];\n    const baseWarn = console.error;\n    console.error = (m) => msg.push(m);\n\n    observer(\n      inject('foo')(\n        class extends Component {\n          render() {\n            return (\n              <div>\n                context:\n                {this.props.foo}\n              </div>\n            );\n          }\n        },\n      ),\n    );\n\n    expect(msg.length).toBe(1);\n    console.error = baseWarn;\n    done();\n  });\n\n  it('observer component can be injected', (done) => {\n    const msg = [];\n    const baseWarn = console.error;\n    console.error = (m) => msg.push(m);\n\n    inject('foo')(\n      observer(\n        class extends Component {\n          render() {\n            return null;\n          }\n        },\n      ),\n    );\n\n    // N.B, the injected component will be observer since mobx-react 4.0!\n    inject(() => {})(\n      observer(\n        class extends Component {\n          render() {\n            return null;\n          }\n        },\n      ),\n    );\n\n    expect(msg.length).toBe(0);\n    console.error = baseWarn;\n    done();\n  });\n\n  it('124 - react to changes in this.props via computed', function () {\n    const Comp = observer(\n      class extends Component {\n        componentWillMount() {\n          extendObservable(this, {\n            get computedProp() {\n              return this.props.x;\n            },\n          });\n        }\n\n        render() {\n          return (\n            <span>\n              x:\n              {this.computedProp}\n            </span>\n          );\n        }\n      },\n    );\n\n    class Parent extends Component {\n      constructor(props) {\n        super(props);\n        this.state = { v: 1 };\n      }\n\n      render() {\n        return (\n          <div\n            onClick={() => {\n              this.setState({ v: 2 });\n            }}\n          >\n            <Comp x={this.state.v} />\n          </div>\n        );\n      }\n    }\n\n    render(<Parent />, container);\n\n    expect(container.querySelector('span').textContent).toBe('x:1');\n    container.querySelector('div').click();\n    expect(container.querySelector('span').textContent).toBe('x:2');\n  });\n\n  it('should render component even if setState called with exactly the same props', function (done) {\n    let renderCount = 0;\n    class Com extends Component {\n      onClick() {\n        this.setState({});\n      }\n\n      render() {\n        renderCount++;\n        return <div onClick={this.onClick.bind(this)} id=\"clickableDiv\" />;\n      }\n    }\n\n    render(<Com />, container);\n\n    expect(renderCount).toBe(1); // 'renderCount === 1');\n    container.querySelector('#clickableDiv').click();\n    expect(renderCount).toBe(2); // 'renderCount === 2');\n    container.querySelector('#clickableDiv').click();\n    expect(renderCount).toBe(3); // 'renderCount === 3');\n    done();\n  });\n\n  it('Observer regions should react', (done) => {\n    const data = observable.box('hi');\n    const Comp = () => (\n      <div>\n        <Observer>{() => <span>{data.get()}</span>}</Observer>\n        <li>{data.get()}</li>\n      </div>\n    );\n    render(<Comp />, container);\n\n    expect(container.querySelector('span').textContent).toBe('hi');\n    expect(container.querySelector('li').textContent).toBe('hi');\n\n    data.set('hello');\n    expect(container.querySelector('span').textContent).toBe('hello');\n    expect(container.querySelector('li').textContent).toBe('hi');\n    done();\n  });\n\n  it('Observer should not re-render on shallow equal new props', () => {\n    let childRendering = 0;\n    let parentRendering = 0;\n    const data = { x: 1 };\n    const odata = observable({ y: 1 });\n\n    const Child = observer(({ data }) => {\n      childRendering++;\n      return <span>{data.x}</span>;\n    });\n    const Parent = observer(() => {\n      parentRendering++;\n      odata.y; /// depend\n      return <Child data={data} />;\n    });\n\n    render(<Parent />, container);\n    expect(parentRendering).toBe(1);\n    expect(childRendering).toBe(1);\n    expect(container.querySelector('span').textContent).toBe('1');\n\n    odata.y++;\n    expect(parentRendering).toBe(2);\n    expect(childRendering).toBe(1);\n    expect(container.querySelector('span').textContent).toBe('1');\n  });\n\n  it('observer should throw on new life cycle hooks', () => {\n    class A extends Component {\n      static getDerivedStateFromProps() {\n        return {};\n      }\n    }\n    expect(() => observer(A)).toThrow();\n    class B extends Component {\n      getSnapshotBeforeUpdate() {\n        return {};\n      }\n    }\n    expect(() => observer(B)).toThrow();\n    expect(() =>\n      observer({\n        render: () => undefined,\n        getSnapshotBeforeUpdate: () => {\n          return {};\n        },\n      }),\n    ).toThrow();\n  });\n\n  it('observer should send exception to errorsReporter and re-thrown', () => {\n    const exception = new Error('dummy error');\n    let reported;\n    const off = onError((error) => {\n      reported = error;\n    });\n    class Faulty extends Component {\n      render() {\n        throw exception;\n      }\n    }\n    observer(Faulty);\n    expect(() => {\n      render(<Faulty />, container);\n    }).toThrow(exception);\n    expect(reported).toEqual(exception);\n    off();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-mobx/__tests__/observerPatch.spec.jsx",
    "content": "import { Component, render } from 'inferno';\nimport { getObserverTree, observable, runInAction } from 'mobx';\nimport { inject, observer, observerPatch } from 'inferno-mobx';\n\ndescribe('Mobx Observer Patch', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('nestedRendering', () => {\n    const store = observable({\n      todos: [\n        {\n          title: 'a',\n          completed: false,\n        },\n      ],\n    });\n\n    let todoItemRenderings = 0;\n    class TodoItem extends Component {\n      render({ todo }) {\n        todoItemRenderings++;\n        return <li>|{todo.title}</li>;\n      }\n\n      shouldComponentUpdate({ todo: { title } }) {\n        return title !== this.props.todo.title;\n      }\n    }\n\n    observerPatch(TodoItem);\n\n    let todoListRenderings = 0;\n    let todoListWillReactCount = 0;\n    class TodoList extends Component {\n      componentWillReact() {\n        todoListWillReactCount++;\n      }\n\n      render() {\n        todoListRenderings++;\n        const todos = store.todos;\n        return (\n          <div>\n            <hi>{todos.length}</hi>\n            {todos.map((todo, idx) => (\n              <TodoItem key={idx} todo={todo} />\n            ))}\n          </div>\n        );\n      }\n    }\n\n    observerPatch(TodoList);\n\n    render(<TodoList />, container);\n    expect(todoListRenderings).toEqual(1); //, 'should have rendered list once');\n    expect(todoListWillReactCount).toEqual(0); //, 'should never call componentWillReact')\n    expect(container.querySelectorAll('li').length).toEqual(1);\n    expect(container.querySelector('li').textContent).toEqual('|a');\n\n    expect(todoItemRenderings).toEqual(1); // 'item1 should render once'\n\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1);\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1);\n\n    store.todos[0].title += 'a';\n\n    expect(todoListRenderings).toEqual(1); //, 'should have rendered list once');\n    expect(todoListWillReactCount).toEqual(0); //, 'should never call componentWillReact')\n    expect(todoItemRenderings).toEqual(2); //, 'item1 should have rendered twice');\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1); //, 'observers count shouldn\\'t change');\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1); //, 'title observers should not have increased');\n\n    store.todos.push({\n      title: 'b',\n      completed: true,\n    });\n\n    expect(container.querySelectorAll('li').length).toBe(2); //, 'list should two items in in the list');\n    const expectedOutput = [];\n    const nodes = container.querySelectorAll('li');\n\n    for (let i = 0; i < nodes.length; i++) {\n      expectedOutput.push(nodes[i].textContent);\n    }\n    expect(expectedOutput).toEqual(['|aa', '|b']);\n\n    expect(todoListRenderings).toBe(2); // 'should have rendered list twice');\n    expect(todoListWillReactCount).toBe(0); //, 'should never call componentWillReact')\n    expect(todoItemRenderings).toBe(3); //, 'item2 should have rendered as well');\n    expect(getObserverTree(store.todos[1], 'title').observers.length).toBe(1); //, 'title observers should have increased');\n    expect(\n      getObserverTree(store.todos[1], 'completed').observers,\n    ).not.toBeDefined(); //, 'completed observers should not have increased');\n\n    const oldTodo = store.todos.pop();\n\n    expect(todoListRenderings).toBe(3); //, 'should have rendered list another time');\n    expect(todoListWillReactCount).toBe(0); //, 'should never call componentWillReact')\n    expect(todoItemRenderings).toBe(3); //, 'item1 should not have rerendered');\n    expect(container.querySelectorAll('li').length).toBe(1); //, 'list should have only on item in list now');\n    expect(getObserverTree(oldTodo, 'title').observers).not.toBeDefined(); //, 'title observers should have decreased');\n    expect(getObserverTree(oldTodo, 'completed').observers).not.toBeDefined(); //, 'completed observers should not have decreased');\n  });\n\n  it('keep views alive', () => {\n    let yCalcCount = 0;\n    const data = observable({\n      x: 3,\n      get y() {\n        yCalcCount++;\n        return this.x * 2;\n      },\n      z: 'hi',\n    });\n\n    class TestComponent extends Component {\n      render() {\n        return (\n          <div>\n            {data.z}\n            {data.y}\n          </div>\n        );\n      }\n    }\n    observerPatch(TestComponent);\n\n    render(<TestComponent />, container);\n    expect(yCalcCount).toBe(1);\n    expect(container.textContent).toBe('hi6');\n\n    data.z = 'hello';\n    // test: rerender should not need a recomputation of data.y because the subscription is kept alive\n\n    expect(yCalcCount).toBe(1);\n\n    expect(container.textContent).toBe('hello6');\n    expect(yCalcCount).toBe(1);\n\n    expect(getObserverTree(data, 'y').observers.length).toBe(1);\n\n    render(<div />, container);\n\n    expect(getObserverTree(data, 'y').observers).not.toBeDefined();\n  });\n\n  it('patched render is run first', (done) => {\n    let origRenderMethod;\n    class Comp extends Component {\n      render() {\n        // ugly check, but proofs that observer.willmount has run\n        // We cannot use function.prototype.name here like in react-redux tests because it is not supported in Edge/IE\n        expect(this.render).not.toBe(origRenderMethod);\n        return null;\n      }\n    }\n\n    origRenderMethod = Comp.prototype.render;\n\n    observerPatch(Comp);\n    render(<Comp />, container);\n    done();\n  });\n\n  it('issue 12', function () {\n    const data = observable({\n      selected: 'coffee',\n      items: [\n        {\n          name: 'coffee',\n        },\n        {\n          name: 'tea',\n        },\n      ],\n    });\n\n    /** Row Class */\n    class Row extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      render() {\n        return (\n          <span>\n            {this.props.item.name}\n            {data.selected === this.props.item.name ? '!' : ''}\n          </span>\n        );\n      }\n    }\n\n    /** table stateles component */\n    class Table extends Component {\n      render() {\n        return (\n          <div>\n            {data.items.map((item) => (\n              <Row key={item.name} item={item} />\n            ))}\n          </div>\n        );\n      }\n    }\n    observerPatch(Table);\n\n    render(<Table />, container);\n\n    expect(container.querySelector('div').textContent).toBe('coffee!tea');\n\n    runInAction(() => {\n      data.items[1].name = 'boe';\n      data.items.splice(0, 2, { name: 'soup' });\n      data.selected = 'tea';\n    });\n\n    expect(container.querySelector('div').textContent).toBe('soup');\n  });\n\n  it('component should not be inject', function (done) {\n    const msg = [];\n    const baseWarn = console.error;\n    console.error = (m) => msg.push(m);\n\n    const Foo = inject('foo')(\n      class FooCom extends Component {\n        render() {\n          return (\n            <div>\n              context:\n              {this.props.foo}\n            </div>\n          );\n        }\n      },\n    );\n    observerPatch(Foo);\n\n    expect(msg.length).toBe(1);\n    console.error = baseWarn;\n    done();\n  });\n\n  it('component should not be observer', function (done) {\n    const msg = [];\n    const baseWarn = console.error;\n    console.error = (m) => msg.push(m);\n\n    const Foo = observer(\n      class FooC extends Component {\n        render() {\n          return (\n            <div>\n              context:\n              {this.props.foo}\n            </div>\n          );\n        }\n      },\n    );\n    observerPatch(Foo);\n\n    expect(msg.length).toBe(1);\n    console.error = baseWarn;\n    done();\n  });\n\n  it('component should not be already be patched', function (done) {\n    const msg = [];\n    const baseWarn = console.error;\n    console.error = (m) => msg.push(m);\n\n    class Foo extends Component {\n      render() {\n        return (\n          <div>\n            context:\n            {this.props.foo}\n          </div>\n        );\n      }\n    }\n    observerPatch(Foo);\n    observerPatch(Foo);\n\n    expect(msg.length).toBe(1);\n    console.error = baseWarn;\n    done();\n  });\n\n  it('observer component can be injected', (done) => {\n    const msg = [];\n    const baseWarn = console.error;\n    console.error = (m) => msg.push(m);\n\n    class fooA extends Component {\n      render() {\n        return null;\n      }\n    }\n    observerPatch(fooA);\n    inject('foo')(fooA);\n\n    // N.B, the injected component will be observer since mobx-react 4.0!\n    class fooB extends Component {\n      render() {\n        return null;\n      }\n    }\n    observerPatch(fooB);\n    inject(() => {})(fooB);\n\n    expect(msg.length).toBe(0);\n    console.error = baseWarn;\n    done();\n  });\n\n  it('should do warn when a patching a class extended from a patched class', (done) => {\n    const msg = [];\n    const baseWarn = console.error;\n    console.error = (m) => msg.push(m);\n\n    class fooA extends Component {\n      render() {\n        return <p>Foo A</p>;\n      }\n    }\n    observerPatch(fooA);\n\n    class fooB extends fooA {\n      render() {\n        return <p>Foo B</p>;\n      }\n    }\n    observerPatch(fooB);\n\n    expect(msg.length).toBe(1);\n    console.error = baseWarn;\n    done();\n  });\n\n  it('should render component even if setState called with exactly the same props', function (done) {\n    let renderCount = 0;\n    class ComponentA extends Component {\n      constructor(props, ctx) {\n        super(props, ctx);\n        this.state = {};\n      }\n\n      onClick() {\n        this.setState({});\n      }\n\n      render() {\n        renderCount++;\n        return <div onClick={this.onClick.bind(this)} id=\"clickableDiv\" />;\n      }\n    }\n    observerPatch(ComponentA);\n    render(<ComponentA />, container);\n\n    expect(renderCount).toBe(1); // 'renderCount === 1');\n    container.querySelector('#clickableDiv').click();\n    expect(renderCount).toBe(2); // 'renderCount === 2');\n    container.querySelector('#clickableDiv').click();\n    expect(renderCount).toBe(3); // 'renderCount === 3');\n    done();\n  });\n\n  it('observerPatch should keep MobX from eating exceptions', () => {\n    const exception = new Error('dummy error');\n    class Faulty extends Component {\n      render() {\n        throw exception;\n      }\n    }\n    observerPatch(Faulty);\n    expect(() => {\n      render(<Faulty />, container);\n    }).toThrow(exception);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-mobx/__tests__/observerWrap.spec.jsx",
    "content": "import { Component, render } from 'inferno';\nimport { inject, observer, observerWrap } from 'inferno-mobx';\nimport { createElement } from 'inferno-create-element';\nimport { getObserverTree, observable, runInAction } from 'mobx';\n\nconst stateLessComp = ({ testProp }) => <div>result: {testProp}</div>;\n\nstateLessComp.defaultProps = {\n  testProp: 'default value for prop testProp',\n};\n\ndescribe('Stateless components observerWrap', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('stateless component', (done) => {\n    const StatelessCompObserver = observerWrap(stateLessComp);\n    expect(StatelessCompObserver.defaultProps.testProp).toBe(\n      'default value for prop testProp',\n    );\n    const wrapper = <StatelessCompObserver testProp={10} />;\n\n    render(<StatelessCompObserver testProp=\"hello world\" />, container);\n\n    expect(container.textContent).toBe('result: hello world');\n    done();\n  });\n\n  it('stateless component with context support', () => {\n    const InnerComp = (_props, context) =>\n      createElement('p', {}, 'inner: ' + context.testContext);\n    const StateLessCompWithContext = ({ store: { value } }, context) => {\n      return createElement('div', {}, [\n        createElement('p', {}, 'value: ' + value + ', '),\n        createElement('p', {}, 'outer: ' + context.testContext + ', '),\n        createElement(InnerComp, {}),\n      ]);\n    };\n    const StateLessCompWithContextObserver = observerWrap(\n      StateLessCompWithContext,\n    );\n    const store = observable({\n      value: 0,\n    });\n    class ContextProvider extends Component {\n      getChildContext() {\n        return { testContext: 'hello' };\n      }\n\n      render() {\n        return <StateLessCompWithContextObserver store={store} />;\n      }\n    }\n    render(<ContextProvider />, container);\n    expect(container.textContent.replace(/\\n/, '')).toBe(\n      'value: 0, outer: hello, inner: hello',\n    );\n    store.value = 1;\n    expect(container.textContent.replace(/\\n/, '')).toBe(\n      'value: 1, outer: hello, inner: hello',\n    );\n  });\n\n  it('nestedRendering', () => {\n    const store = observable({\n      todos: [\n        {\n          title: 'a',\n          completed: false,\n        },\n      ],\n    });\n\n    let todoItemRenderings = 0;\n    let todoItemUnmounts = 0;\n    let todoItemUpdates = 0;\n    let todoItemWillUpdates = 0;\n    const TodoItemBase = ({ todo }) => {\n      todoItemRenderings++;\n      return <li>|{todo.title}</li>;\n    };\n    TodoItemBase.defaultHooks = {\n      onComponentDidUpdate: () => {\n        todoItemUpdates++;\n      },\n      onComponentShouldUpdate: (\n        { todo: { title: prev } },\n        { todo: { title: next } },\n      ) => {\n        return prev !== next;\n      },\n      onComponentWillUnmount: () => {\n        todoItemUnmounts++;\n      },\n      onComponentWillUpdate: () => {\n        todoItemWillUpdates++;\n      },\n    };\n    const TodoItem = observerWrap(TodoItemBase);\n\n    let todoListRenderings = 0;\n    const TodoList = observerWrap(() => {\n      todoListRenderings++;\n      const todos = store.todos;\n      return (\n        <div>\n          <p>{todos.length}</p>\n          {todos.map((todo, idx) => (\n            <TodoItem key={idx} todo={todo} />\n          ))}\n        </div>\n      );\n    });\n\n    render(<TodoList />, container);\n    expect(todoListRenderings).toEqual(1); //, 'should have rendered list once');\n    expect(container.querySelectorAll('li').length).toEqual(1);\n    expect(container.querySelector('li').textContent).toEqual('|a');\n\n    expect(todoItemRenderings).toEqual(1); // 'item1 should render once'\n\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1);\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1);\n\n    store.todos[0].title += 'a';\n\n    expect(todoListRenderings).toEqual(1); //, 'should have rendered list once');\n    expect(todoItemRenderings).toEqual(2); //, 'item1 should have rendered twice');\n    expect(container.querySelector('li').textContent).toEqual('|aa');\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1); //, 'observers count shouldn\\'t change');\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1); //, 'title observers should not have increased');\n\n    store.todos.push({\n      title: 'b',\n      completed: true,\n    });\n\n    expect(container.querySelectorAll('li').length).toBe(2); //, 'list should two items in in the list');\n    let expectedOutput = [];\n    let nodes = container.querySelectorAll('li');\n\n    for (let i = 0; i < nodes.length; i++) {\n      expectedOutput.push(nodes[i].textContent);\n    }\n    expect(expectedOutput).toEqual(['|aa', '|b']);\n\n    expect(todoListRenderings).toBe(2); // 'should have rendered list twice');\n    expect(todoItemRenderings).toBe(3); //, 'item2 should have rendered as well');\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1); //, 'observers count shouldn\\'t change');\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1); //, 'title observers should not have increased');\n    expect(getObserverTree(store.todos[1], 'title').observers.length).toBe(1); //, 'title observers should have increased');\n    expect(\n      getObserverTree(store.todos[1], 'completed').observers,\n    ).not.toBeDefined(); //, 'completed observers should not have increased');\n\n    store.todos[1].title += 'b';\n\n    expect(container.querySelectorAll('li').length).toBe(2); //, 'list should two items in in the list');\n    expectedOutput = [];\n    nodes = container.querySelectorAll('li');\n\n    for (let i = 0; i < nodes.length; i++) {\n      expectedOutput.push(nodes[i].textContent);\n    }\n    expect(expectedOutput).toEqual(['|aa', '|bb']);\n\n    expect(todoListRenderings).toBe(2); // 'should have rendered list twice');\n    expect(todoItemRenderings).toBe(4); //, 'item2 should have rendered as well');\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1); //, 'observers count shouldn\\'t change');\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1); //, 'title observers should not have increased');\n    expect(getObserverTree(store.todos[1], 'title').observers.length).toBe(1); //, 'title observers should have increased');\n    expect(\n      getObserverTree(store.todos[1], 'completed').observers,\n    ).not.toBeDefined(); //, 'completed observers should not have increased');\n\n    const oldTodo = store.todos.pop();\n\n    expect(todoListRenderings).toBe(3); //, 'should have rendered list another time');\n    expect(todoItemRenderings).toBe(4); //, 'item1 should not have rerendered');\n    expect(container.querySelectorAll('li').length).toBe(1); //, 'list should have only on item in list now');\n    expect(getObserverTree(oldTodo, 'title').observers).not.toBeDefined(); //, 'title observers should have decreased');\n    expect(getObserverTree(oldTodo, 'completed').observers).not.toBeDefined(); //, 'completed observers should not have decreased');\n    render(null, container);\n    expect(todoItemUnmounts).toBe(2);\n    expect(todoItemUpdates).toBe(2);\n    expect(todoItemWillUpdates).toBe(2);\n    expect(getObserverTree(store, 'todos').observers).not.toBeDefined();\n    expect(\n      getObserverTree(store.todos[0], 'title').observers,\n    ).not.toBeDefined();\n  });\n\n  it('nestedRendering without should update hook', () => {\n    const store = observable({\n      todos: [\n        {\n          title: 'a',\n          completed: false,\n        },\n      ],\n    });\n\n    let todoItemRenderings = 0;\n    let todoItemUnmounts = 0;\n    let todoItemUpdates = 0;\n    let todoItemWillUpdates = 0;\n    const TodoItemBase = ({ todo }) => {\n      todoItemRenderings++;\n      return <li>|{todo.title}</li>;\n    };\n    TodoItemBase.defaultHooks = {\n      onComponentDidUpdate: () => {\n        todoItemUpdates++;\n      },\n      onComponentWillUnmount: () => {\n        todoItemUnmounts++;\n      },\n      onComponentWillUpdate: () => {\n        todoItemWillUpdates++;\n      },\n    };\n    const TodoItem = observerWrap(TodoItemBase);\n\n    let todoListRenderings = 0;\n    const TodoList = observerWrap(() => {\n      todoListRenderings++;\n      const todos = store.todos;\n      return (\n        <div>\n          <p>{todos.length}</p>\n          {todos.map((todo, idx) => (\n            <TodoItem key={idx} todo={todo} />\n          ))}\n        </div>\n      );\n    });\n\n    render(<TodoList />, container);\n    expect(todoListRenderings).toEqual(1); //, 'should have rendered list once');\n    expect(container.querySelectorAll('li').length).toEqual(1);\n    expect(container.querySelector('li').textContent).toEqual('|a');\n\n    expect(todoItemRenderings).toEqual(1); // 'item1 should render once'\n\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1);\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1);\n\n    store.todos[0].title += 'a';\n\n    expect(todoListRenderings).toEqual(1); //, 'should have rendered list once');\n    expect(todoItemRenderings).toEqual(2); //, 'item1 should have rendered twice');\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1); //, 'observers count shouldn\\'t change');\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1); //, 'title observers should not have increased');\n\n    store.todos.push({\n      title: 'b',\n      completed: true,\n    });\n\n    expect(container.querySelectorAll('li').length).toBe(2); //, 'list should two items in in the list');\n    let expectedOutput = [];\n    let nodes = container.querySelectorAll('li');\n\n    for (let i = 0; i < nodes.length; i++) {\n      expectedOutput.push(nodes[i].textContent);\n    }\n    expect(expectedOutput).toEqual(['|aa', '|b']);\n\n    expect(todoListRenderings).toBe(2); // 'should have rendered list twice');\n    expect(todoItemRenderings).toBe(4); //, 'item2 should have rendered as well');\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1); //, 'observers count shouldn\\'t change');\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1); //, 'title observers should not have increased');\n    expect(getObserverTree(store.todos[1], 'title').observers.length).toBe(1); //, 'title observers should have increased');\n    expect(\n      getObserverTree(store.todos[1], 'completed').observers,\n    ).not.toBeDefined(); //, 'completed observers should not have increased');\n\n    store.todos[1].title += 'b';\n\n    expect(container.querySelectorAll('li').length).toBe(2); //, 'list should two items in in the list');\n    expectedOutput = [];\n    nodes = container.querySelectorAll('li');\n\n    for (let i = 0; i < nodes.length; i++) {\n      expectedOutput.push(nodes[i].textContent);\n    }\n    expect(expectedOutput).toEqual(['|aa', '|bb']);\n\n    expect(todoListRenderings).toBe(2); // 'should have rendered list twice');\n    expect(todoItemRenderings).toBe(5); //, 'item2 should have rendered as well');\n    expect(getObserverTree(store, 'todos').observers.length).toBe(1); //, 'observers count shouldn\\'t change');\n    expect(getObserverTree(store.todos[0], 'title').observers.length).toBe(1); //, 'title observers should not have increased');\n    expect(getObserverTree(store.todos[1], 'title').observers.length).toBe(1); //, 'title observers should have increased');\n    expect(\n      getObserverTree(store.todos[1], 'completed').observers,\n    ).not.toBeDefined(); //, 'completed observers should not have increased');\n\n    const oldTodo = store.todos.pop();\n\n    expect(todoListRenderings).toBe(3); //, 'should have rendered list another time');\n    expect(todoItemRenderings).toBe(6); //, 'item1 should not have rerendered');\n    expect(container.querySelectorAll('li').length).toBe(1); //, 'list should have only on item in list now');\n    expect(getObserverTree(oldTodo, 'title').observers).not.toBeDefined(); //, 'title observers should have decreased');\n    expect(getObserverTree(oldTodo, 'completed').observers).not.toBeDefined(); //, 'completed observers should not have decreased');\n    render(null, container);\n    expect(todoItemUnmounts).toBe(2);\n    expect(todoItemUpdates).toBe(4);\n    expect(todoItemWillUpdates).toBe(4);\n    expect(getObserverTree(store, 'todos').observers).not.toBeDefined();\n    expect(\n      getObserverTree(store.todos[0], 'title').observers,\n    ).not.toBeDefined();\n  });\n\n  it('keep views alive', () => {\n    let yCalcCount = 0;\n    const data = observable({\n      x: 3,\n      get y() {\n        yCalcCount++;\n        return this.x * 2;\n      },\n      z: 'hi',\n    });\n\n    const TestComponent = observerWrap(() => {\n      return (\n        <div>\n          {data.z}\n          {data.y}\n        </div>\n      );\n    });\n\n    render(<TestComponent />, container);\n    expect(yCalcCount).toBe(1);\n    expect(container.textContent).toBe('hi6');\n\n    data.z = 'hello';\n    // test: rerender should not need a recomputation of data.y because the subscription is kept alive\n\n    expect(yCalcCount).toBe(1);\n\n    expect(container.textContent).toBe('hello6');\n    expect(yCalcCount).toBe(1);\n\n    expect(getObserverTree(data, 'y').observers.length).toBe(1);\n\n    render(<div />, container);\n\n    expect(getObserverTree(data, 'y').observers).not.toBeDefined();\n  });\n\n  it('issue 12', function () {\n    const data = observable({\n      selected: 'coffee',\n      items: [\n        {\n          name: 'coffee',\n        },\n        {\n          name: 'tea',\n        },\n      ],\n    });\n\n    const Row = observerWrap(({ item }) => {\n      return (\n        <span>\n          {item.name}\n          {data.selected === item.name ? '!' : ''}\n        </span>\n      );\n    });\n\n    const Table = observerWrap(() => {\n      return (\n        <div>\n          {data.items.map((item) => (\n            <Row key={item.name} item={item} />\n          ))}\n        </div>\n      );\n    });\n\n    render(<Table />, container);\n\n    expect(container.querySelector('div').textContent).toBe('coffee!tea');\n\n    runInAction(() => {\n      data.items[1].name = 'boe';\n      data.items.splice(0, 2, { name: 'soup' });\n      data.selected = 'tea';\n    });\n\n    expect(container.querySelector('div').textContent).toBe('soup');\n  });\n\n  it('Callbacks are bound on render', function () {\n    const data = observable({\n      name: 'tea',\n    });\n\n    let a = 0;\n    let x = 0;\n    let y = 0;\n    let z = 0;\n\n    const ViewFn = ({ item }) => {\n      return <span>{item.name}</span>;\n    };\n\n    const View = observerWrap(ViewFn);\n\n    const check = ({ item: prev }, { item: next }) => prev !== next;\n\n    render(\n      <View\n        item={data}\n        onComponentWillUpdate={(p, n) => (p !== n ? a++ : x++)}\n      />,\n      container,\n    );\n\n    expect(a).toBe(0);\n    expect(x).toBe(0);\n\n    runInAction(() => {\n      data.name = 'coffee';\n    });\n\n    expect(x).toBe(1);\n\n    render(\n      <View\n        item={data}\n        onComponentWillUpdate={(p, n) => (p !== n ? a++ : y++)}\n      />,\n      container,\n    );\n\n    expect(a).toBe(1);\n    expect(x).toBe(1);\n    expect(y).toBe(0);\n\n    runInAction(() => {\n      data.name = 'soda';\n    });\n\n    expect(a).toBe(1);\n    expect(x).toBe(1);\n    expect(y).toBe(1);\n\n    render(\n      <View\n        item={data}\n        onComponentWillUpdate={(p, n) => (p !== n ? a++ : z++)}\n        onComponentShouldUpdate={check}\n      />,\n      container,\n    );\n\n    expect(a).toBe(1);\n    expect(z).toBe(0);\n    expect(y).toBe(1);\n\n    runInAction(() => {\n      data.name = 'water';\n    });\n\n    expect(y).toBe(2);\n\n    render(\n      <View\n        item={data}\n        onComponentWillUpdate={(p, n) => (p !== n ? a++ : x++)}\n      />,\n      container,\n    );\n\n    expect(a).toBe(2);\n    expect(x).toBe(1);\n    expect(y).toBe(2);\n\n    runInAction(() => {\n      data.name = 'juice';\n    });\n\n    expect(a).toBe(2);\n    expect(y).toBe(2);\n    expect(x).toBe(2);\n  });\n\n  it('component should not be inject', () => {\n    const Foo = ({ foo }) => {\n      return (\n        <div>\n          context:\n          {foo}\n        </div>\n      );\n    };\n    // inject wraps in a class component, which will make observerWrap throw\n    expect(() => observerWrap(observer(Foo))).toThrow();\n  });\n\n  it('component should not be observer', () => {\n    const Foo = ({ foo }) => {\n      return (\n        <div>\n          context:\n          {foo}\n        </div>\n      );\n    };\n    // observer wraps in a class component, which will make observerWrap throw\n    expect(() => observerWrap(observer(Foo))).toThrow();\n  });\n\n  it('component should not be already be wrapped', () => {\n    const msg = [];\n    const baseWarn = console.error;\n    console.error = (m) => msg.push(m);\n\n    observerWrap(\n      observerWrap(({ foo }) => {\n        return (\n          <div>\n            context:\n            {foo}\n          </div>\n        );\n      }),\n    );\n\n    expect(msg.length).toBe(1);\n    console.error = baseWarn;\n  });\n\n  it('observer component can be injected', (done) => {\n    const msg = [];\n    const baseWarn = console.error;\n    console.error = (m) => msg.push(m);\n\n    const fooA = inject('foo')(observerWrap(() => null));\n\n    render(<fooA />, container);\n\n    // N.B, the injected component will be observer since mobx-react 4.0!\n    const fooB = inject(() => {})(observerWrap(() => null));\n\n    expect(msg.length).toBe(0);\n    console.error = baseWarn;\n    done();\n  });\n\n  it('observerWrap should keep MobX from eating exceptions', () => {\n    const exception = new Error('dummy error');\n    const Faulty = observerWrap(() => {\n      throw exception;\n    });\n    expect(() => {\n      render(<Faulty />, container);\n    }).toThrow(exception);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-mobx/__tests__/stateless.spec.jsx",
    "content": "import { Component, render } from 'inferno';\nimport { observer } from 'inferno-mobx';\nimport { createElement } from 'inferno-create-element';\n\nconst stateLessComp = ({ testProp }) => <div>result: {testProp}</div>;\n\nstateLessComp.defaultProps = {\n  testProp: 'default value for prop testProp',\n};\n\ndescribe('Stateless components MOBX', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('stateless component', (done) => {\n    const StatelessCompObserver = observer(stateLessComp);\n    expect(StatelessCompObserver.defaultProps.testProp).toBe(\n      'default value for prop testProp',\n    );\n    const wrapper = <StatelessCompObserver testProp={10} />;\n\n    render(<StatelessCompObserver testProp=\"hello world\" />, container);\n\n    expect(container.textContent).toBe('result: hello world');\n    done();\n  });\n\n  it('stateless component with context support', (done) => {\n    const StateLessCompWithContext = (props, context) =>\n      createElement('div', {}, 'context: ' + context.testContext);\n    const StateLessCompWithContextObserver = observer(StateLessCompWithContext);\n\n    class ContextProvider extends Component {\n      getChildContext() {\n        return { testContext: 'hello world' };\n      }\n\n      render() {\n        return <StateLessCompWithContextObserver />;\n      }\n    }\n\n    render(<ContextProvider />, container);\n    expect(container.textContent.replace(/\\n/, '')).toBe(\n      'context: hello world',\n    );\n    done();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-mobx/__tests__/transactions.spec.jsx",
    "content": "import { Component, render } from 'inferno';\nimport { observer } from 'inferno-mobx';\nimport { autorun, computed, observable, runInAction } from 'mobx';\n\ndescribe('Mobx Transacations', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('mobx issue 50', () => {\n    const foo = {\n      a: observable.box(true),\n      b: observable.box(false),\n      c: computed(function () {\n        return foo.b.get();\n      }),\n    };\n    function flipStuff() {\n      runInAction(() => {\n        foo.a.set(!foo.a.get());\n        foo.b.set(!foo.b.get());\n      });\n    }\n    let asText = '';\n    let willReactCount = 0;\n    autorun(() => (asText = [foo.a.get(), foo.b.get(), foo.c.get()].join(':')));\n\n    const Test = observer(\n      class MyCom extends Component {\n        componentWillReact() {\n          willReactCount++;\n        }\n\n        render() {\n          return (\n            <div id=\"x\">\n              {[foo.a.get(), foo.b.get(), foo.c.get()].join(',')}\n            </div>\n          );\n        }\n      },\n    );\n\n    render(<Test />, container);\n    // In 3 seconds, flip a and b. This will change c.\n    flipStuff();\n\n    expect(asText).toBe('false:true:true');\n    expect(document.getElementById('x').textContent).toBe('false,true,true');\n    expect(willReactCount).toBe(1);\n  });\n\n  it('React.render should respect transaction', () => {\n    const a = observable.box(2);\n    const loaded = observable.box(false);\n    const valuesSeen = [];\n\n    const Component = observer(() => {\n      valuesSeen.push(a.get());\n      if (loaded.get()) return <div>{a.get()}</div>;\n      else return <div>loading</div>;\n    });\n\n    render(<Component />, container);\n    runInAction(() => {\n      a.set(3);\n      a.set(4);\n      loaded.set(true);\n    });\n\n    expect(container.textContent.replace(/\\s+/g, '')).toBe('4');\n    expect(valuesSeen).toEqual([2, 4]);\n  });\n\n  it('React.render in transaction should succeed', () => {\n    const a = observable.box(2);\n    const loaded = observable.box(false);\n    const valuesSeen = [];\n    const Component = observer(() => {\n      valuesSeen.push(a.get());\n      if (loaded.get()) return <div>{a.get()}</div>;\n      else return <div>loading</div>;\n    });\n\n    runInAction(() => {\n      a.set(3);\n      render(<Component />, container);\n      a.set(4);\n      loaded.set(true);\n    });\n\n    expect(container.textContent.replace(/\\s+/g, '')).toBe('4');\n    expect(valuesSeen).toEqual([3, 4]);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-mobx/__tests__/types.spec.tsx",
    "content": "import { Component, FormEvent, render } from 'inferno';\nimport { Provider } from 'inferno-mobx';\nimport { observable } from 'mobx';\n\ndescribe('top level context', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  describe('Rendering types', () => {\n    it('Should render SFC', () => {\n      // SFC\n      const MyComponent = (props) => {\n        return <div>{props.children}</div>;\n      };\n\n      render(<MyComponent />, container);\n    });\n\n    it('Should be possible to return string from render SFC', () => {\n      // SFC\n      const MyComponent = () => {\n        return 'd';\n      };\n\n      render(<MyComponent />, container);\n    });\n\n    it('Should be possible to return number from render SFC', () => {\n      // SFC\n      const MyComponent = () => {\n        return 1;\n      };\n\n      render(<MyComponent />, container);\n    });\n\n    it('Should not complain about onInput event.target', () => {\n      render(\n        <input onInput={(e: FormEvent<HTMLInputElement>) => e.target.value} />,\n        container,\n      );\n    });\n\n    it('Should be possible to return null from render SFC', () => {\n      // SFC\n      const MyComponent = () => {\n        return null;\n      };\n\n      render(<MyComponent />, container);\n    });\n\n    it('Should render Provider', () => {\n      class MyComponent extends Component {\n        public render() {\n          return <div>1</div>;\n        }\n      }\n\n      const store = observable({\n        todos: [\n          {\n            completed: false,\n            title: 'a',\n          },\n        ],\n      });\n\n      render(\n        <Provider store={store}>\n          <MyComponent />\n        </Provider>,\n        container,\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-mobx/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-mobx/package.json",
    "content": "{\n  \"name\": \"inferno-mobx\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Official Inferno bindings for Mobx\",\n  \"author\": {\n    \"name\": \"Ryan Megidov\",\n    \"email\": \"ryan@megidov.com\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"files\": [\n    \"index.cjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"keywords\": [\n    \"babel\",\n    \"inferno\",\n    \"framework\",\n    \"interfaces\",\n    \"reactive\",\n    \"mobservable\",\n    \"mobx\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-mobx\"\n  },\n  \"peerDependencies\": {\n    \"mobx\": \">=6\"\n  },\n  \"dependencies\": {\n    \"inferno\": \"9.0.11\"\n  },\n  \"devDependencies\": {\n    \"inferno-create-element\": \"9.0.11\",\n    \"inferno-shared\": \"9.0.11\",\n    \"inferno-vnode-flags\": \"9.0.11\",\n    \"mobx\": \"*\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\"\n    ],\n    \"moduleName\": \"Inferno.Mobx\",\n    \"moduleGlobals\": {\n      \"inferno\": \"Inferno\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno-mobx/src/Provider.ts",
    "content": "import { Component, type InfernoNode } from 'inferno';\nimport { warning } from 'inferno-shared';\n\nconst specialKeys = {\n  children: true,\n  key: true,\n  ref: true,\n};\n\nexport class Provider extends Component<any, any> {\n  public render(props): InfernoNode {\n    return props.children;\n  }\n\n  public getChildContext(): { mobxStores: any } {\n    const stores = {} as any;\n    // inherit stores\n    const props = this.props;\n    const baseStores = this.context.mobxStores;\n\n    if (baseStores) {\n      for (const key in baseStores) {\n        stores[key] = baseStores[key];\n      }\n    }\n    // add own stores\n    for (const key in props) {\n      if (\n        (specialKeys as any)[key] === void 0 &&\n        key !== 'suppressChangedStoreWarning'\n      ) {\n        stores[key] = props[key];\n      }\n    }\n\n    return {\n      mobxStores: stores,\n    };\n  }\n}\n\n// Development warning\nif (process.env.NODE_ENV !== 'production') {\n  Provider.prototype.componentWillReceiveProps = function (nextProps) {\n    // Maybe this warning is too aggressive?\n    if (Object.keys(nextProps).length !== Object.keys(this.props).length) {\n      warning(\n        'MobX Provider: The set of provided stores has changed. Please avoid changing stores as the change might not propagate to all children',\n      );\n    }\n\n    if (!nextProps.suppressChangedStoreWarning) {\n      for (const key in nextProps) {\n        if (\n          (specialKeys as any)[key] === void 0 &&\n          this.props[key] !== nextProps[key]\n        ) {\n          warning(\n            \"MobX Provider: Provided store '\" +\n              key +\n              \"' has changed. Please avoid replacing stores as the change might not propagate to all children\",\n          );\n        }\n      }\n    }\n  };\n}\n"
  },
  {
    "path": "packages/inferno-mobx/src/index.ts",
    "content": "import {\n  errorsReporter,\n  inject,\n  Observer,\n  observer,\n  renderReporter,\n  trackComponents,\n  useStaticRendering,\n} from './observer';\nimport { Provider } from './Provider';\nimport { EventEmitter } from './utils/EventEmitter';\nimport { observerPatch } from './observerPatch';\nimport { observerWrap } from './observerWrap';\n\n// THIS IS PORT OF AWESOME MOBX-REACT to INFERNO\n// LAST POINT OF PORT\n// https://github.com/mobxjs/mobx-react/commit/a1e05d93efd4d9ac819e865e96af138bc6d2ad75\n\nfunction onError(fn: (data: unknown) => void): () => void {\n  return errorsReporter.on(fn);\n}\n\nexport {\n  errorsReporter,\n  inject,\n  observer,\n  onError,\n  EventEmitter,\n  Observer,\n  observerPatch,\n  observerWrap,\n  Provider,\n  renderReporter,\n  trackComponents,\n  useStaticRendering,\n};\n"
  },
  {
    "path": "packages/inferno-mobx/src/observer.ts",
    "content": "import { _allowStateChanges, createAtom, Reaction } from 'mobx';\nimport {\n  Component,\n  createComponentVNode,\n  type InfernoNode,\n  type VNode,\n} from 'inferno';\nimport { EventEmitter } from './utils/EventEmitter';\nimport { warning, hoistStaticProperties } from 'inferno-shared';\nimport { isStateless } from './utils/utils';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\n/**\n * dev tool support\n */\nlet isDevtoolsEnabled = false;\n\nlet isUsingStaticRendering = false;\n\nlet warnedAboutObserverInjectDeprecation = false;\n\nexport const renderReporter = new EventEmitter();\n\nfunction reportRendering(component): void {\n  const node = component.$LI.dom;\n\n  renderReporter.emit({\n    component,\n    event: 'render',\n    node,\n    renderTime: component.__$mobRenderEnd - component.__$mobRenderStart,\n    totalTime: Date.now() - component.__$mobRenderStart,\n  });\n}\n\nexport function trackComponents(): void {\n  if (!isDevtoolsEnabled) {\n    isDevtoolsEnabled = true;\n    warning(\n      'Do not turn trackComponents on in production, its expensive. For tracking dom nodes you need inferno-compat.',\n    );\n  } else {\n    isDevtoolsEnabled = false;\n    renderReporter.listeners.length = 0;\n  }\n}\n\nexport function useStaticRendering(useStatic: boolean): void {\n  isUsingStaticRendering = useStatic;\n}\n\n/**\n * Errors reporter\n */\n\nexport const errorsReporter = new EventEmitter();\n\n/**\n * Utilities\n */\n\nfunction patch(target, funcName, runMixinFirst): void {\n  const base = target[funcName];\n  const mixinFunc = reactiveMixin[funcName];\n  const f = !base\n    ? mixinFunc\n    : runMixinFirst === true\n      ? function (...args) {\n          mixinFunc.apply(this, ...args);\n          base.apply(this, ...args);\n        }\n      : function (...args) {\n          base.apply(this, ...args);\n          mixinFunc.apply(this, ...args);\n        };\n\n  // MWE: ideally we freeze here to protect against accidental overwrites in component instances, see #195\n  // ...but that breaks react-hot-loader, see #231...\n  target[funcName] = f;\n}\n\nfunction isObjectShallowModified(prev, next): boolean {\n  if (\n    prev == null ||\n    next == null ||\n    typeof prev !== 'object' ||\n    typeof next !== 'object'\n  ) {\n    return prev !== next;\n  }\n  const keys = Object.keys(prev);\n  if (keys.length !== Object.keys(next).length) {\n    return true;\n  }\n  let key;\n  for (let i = keys.length - 1; i >= 0; i--) {\n    key = keys[i];\n    if (next[key] !== prev[key]) {\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * ReactiveMixin\n */\n\nconst reactiveMixin = {\n  componentWillMount() {\n    if (isUsingStaticRendering) {\n      return;\n    }\n\n    // Generate friendly name for debugging\n    const initialName =\n      this.displayName ||\n      this.name ||\n      (this.constructor &&\n        (this.constructor.displayName || this.constructor.name)) ||\n      '<component>';\n\n    /**\n     * If props are shallowly modified, React will render anyway,\n     * so atom.reportChanged() should not result in yet another re-render\n     */\n    let skipRender = false;\n    /**\n     * forceUpdate will re-assign this.props. We don't want that to cause a loop,\n     * so detect these changes\n     */\n\n    function makePropertyObservableReference(propName): void {\n      let valueHolder = this[propName];\n      const atom = createAtom('reactive ' + propName);\n      Object.defineProperty(this, propName, {\n        configurable: true,\n        enumerable: true,\n        get() {\n          atom.reportObserved();\n          return valueHolder;\n        },\n        set(v) {\n          if (isObjectShallowModified(valueHolder, v)) {\n            valueHolder = v;\n            skipRender = true;\n            atom.reportChanged();\n            skipRender = false;\n          } else {\n            valueHolder = v;\n          }\n        },\n      });\n    }\n\n    // make this.props an observable reference, see #124\n    makePropertyObservableReference.call(this, 'props');\n    // make state an observable reference\n    makePropertyObservableReference.call(this, 'state');\n\n    // wire up reactive render\n    const render = this.render.bind(this);\n    const baseRender = (): InfernoNode =>\n      render(this.props, this.state, this.context);\n    let reaction: Reaction | null = null;\n    let isRenderingPending = false;\n\n    const initialRender = (): InfernoNode => {\n      reaction = new Reaction(`${initialName}.render()`, () => {\n        if (!isRenderingPending) {\n          // N.B. Getting here *before mounting* means that a component constructor has side effects (see the relevant test in misc.js)\n          // This unidiomatic React usage but React will correctly warn about this so we continue as usual\n          // See #85 / Pull #44\n          isRenderingPending = true;\n          if (typeof this.componentWillReact === 'function') {\n            this.componentWillReact(); // TODO: wrap in action?\n          }\n          if (!skipRender) {\n            this.forceUpdate();\n          }\n        }\n      });\n      reaction.reactComponent = this;\n      (reactiveRender as any).$mobx = reaction;\n      (reactiveRender as any).$base = this.render;\n      this.render = reactiveRender;\n      return reactiveRender();\n    };\n\n    const reactiveRender = (): InfernoNode => {\n      isRenderingPending = false;\n      let exception;\n      let rendering = null;\n\n      reaction.track(() => {\n        if (isDevtoolsEnabled) {\n          this.__$mobRenderStart = Date.now();\n        }\n        try {\n          rendering = _allowStateChanges(false, baseRender);\n        } catch (e) {\n          exception = e;\n        }\n        if (isDevtoolsEnabled) {\n          this.__$mobRenderEnd = Date.now();\n        }\n      });\n      if (exception) {\n        errorsReporter.emit(exception);\n        throw exception;\n      }\n      return rendering;\n    };\n\n    this.render = initialRender;\n  },\n\n  componentWillUnmount() {\n    if (isUsingStaticRendering) {\n      return;\n    }\n\n    if (this.render.$mobx) {\n      this.render.$mobx.dispose();\n      this.render = this.render.$base;\n    }\n\n    if (isDevtoolsEnabled) {\n      const node = this.$LI.dom;\n\n      renderReporter.emit({\n        component: this,\n        event: 'destroy',\n        node,\n      });\n    }\n  },\n\n  componentDidMount() {\n    if (isDevtoolsEnabled) {\n      reportRendering(this);\n    }\n  },\n\n  componentDidUpdate() {\n    if (isDevtoolsEnabled) {\n      reportRendering(this);\n    }\n  },\n\n  shouldComponentUpdate(nextProps, nextState) {\n    if (isUsingStaticRendering) {\n      warning(\n        '[mobx-react] It seems that a re-rendering of a React component is triggered while in static (server-side) mode. Please make sure components are rendered only once server-side.',\n      );\n    }\n    // update on any state changes (as is the default)\n    if (this.state !== nextState) {\n      return true;\n    }\n    // update if props are shallowly not equal, inspired by PureRenderMixin\n    // we could return just 'false' here, and avoid the `skipRender` checks etc\n    // however, it is nicer if lifecycle events are triggered like usually,\n    // so we return true here if props are shallowly modified.\n    return isObjectShallowModified(this.props, nextProps);\n  },\n};\n\n/**\n * Observer function / decorator\n */\nexport function observer(stores: string[]): <T>(clazz: T) => void;\nexport function observer<T>(stores: string[], clazz: T): T;\nexport function observer<T>(target: T): T;\n\nexport function observer(arg1, arg2?) {\n  if (typeof arg1 === 'string') {\n    throw new Error('Store names should be provided as array');\n  }\n  if (Array.isArray(arg1)) {\n    // component needs stores\n    if (!warnedAboutObserverInjectDeprecation) {\n      warnedAboutObserverInjectDeprecation = true;\n      warning(\n        'Mobx observer: Using observer to inject stores is deprecated since 4.0. Use `@inject(\"store1\", \"store2\") @observer ComponentClass` or `inject(\"store1\", \"store2\")(observer(componentClass))` instead of `@observer([\"store1\", \"store2\"]) ComponentClass`',\n      );\n    }\n    if (!arg2) {\n      // invoked as decorator\n      return (componentClass) => observer(arg1, componentClass);\n    } else {\n      // eslint-disable-next-line prefer-spread\n      return (inject as any).apply(null, arg1)(observer(arg2));\n    }\n  }\n  const component = arg1;\n\n  if (component.isMobxInjector === true) {\n    warning(\n      \"Mobx observer: You are trying to use 'observer' on a component that already has 'inject'. Please apply 'observer' before applying 'inject'\",\n    );\n  }\n\n  // Stateless function component:\n  // If it is function but doesn't seem to be a React class constructor,\n  // wrap it to a React class automatically\n  if (typeof component === 'function' && !component.prototype?.render) {\n    return observer(\n      class<P, S> extends Component<P, S> {\n        public static displayName = component.displayName || component.name;\n        public static defaultProps = component.defaultProps;\n        public render(props, _state, context): InfernoNode {\n          return component(props, context);\n        }\n      },\n    );\n  }\n\n  if (!component) {\n    throw new Error(\"Please pass a valid component to 'observer'\");\n  }\n\n  const target = component.prototype || component;\n  if (process.env.NODE_ENV !== 'production') {\n    if (\n      component.prototype &&\n      typeof component.getDerivedStateFromProps === 'function'\n    ) {\n      throw new Error(\n        \"inferno-mobx 'observer' is incompatible with the 'getDerivedStateFromProps' life cycle hook.\",\n      );\n    }\n    if (typeof target.getSnapshotBeforeUpdate === 'function') {\n      throw new Error(\n        \"inferno-mobx 'observer' is incompatible with the 'getSnapshotBeforeUpdate' life cycle hook.\",\n      );\n    }\n  }\n  mixinLifecycleEvents(target);\n  component.isMobXReactObserver = true;\n  return component;\n}\n\nfunction mixinLifecycleEvents(target): void {\n  patch(target, 'componentWillMount', true);\n  patch(target, 'componentDidMount', false);\n  patch(target, 'componentWillUnmount', false);\n  patch(target, 'componentDidUpdate', false);\n  if (!target.shouldComponentUpdate) {\n    target.shouldComponentUpdate = reactiveMixin.shouldComponentUpdate;\n  }\n}\n\n// TODO: support injection somehow as well?\nexport const Observer = observer(({ children }) => children());\n\n(Observer as any).displayName = 'Observer';\n\nconst proxiedInjectorProps = {\n  isMobxInjector: {\n    configurable: true,\n    enumerable: true,\n    value: true,\n    writable: true,\n  },\n};\n\n/**\n * Store Injection\n */\n\nfunction createStoreInjector(grabStoresFn: Function, component, injectNames?) {\n  let displayName =\n    'inject-' +\n    (component.displayName ||\n      component.name ||\n      component.constructor?.name ||\n      'Unknown');\n  if (injectNames) {\n    displayName += '-with-' + injectNames;\n  }\n\n  class Injector<P, S> extends Component<P, S> {\n    constructor(props, context) {\n      super(props, context);\n\n      this.storeRef = this.storeRef.bind(this);\n    }\n\n    public static displayName = displayName;\n    public static wrappedComponent;\n    public static isMobxInjector: boolean = false;\n\n    public wrappedInstance: Component<P, S> | Function | null;\n\n    public storeRef(instance): void {\n      this.wrappedInstance = instance;\n    }\n\n    public render(props, _state, context): VNode {\n      // Optimization: it might be more efficient to apply the mapper function *outside* the render method\n      // (if the mapper is a function), that could avoid expensive(?) re-rendering of the injector component\n      // See this test: 'using a custom injector is not too reactive' in inject.js\n      const newProps = {};\n      let key;\n\n      for (key in props) {\n        newProps[key] = props[key];\n      }\n\n      const additionalProps =\n        grabStoresFn(context.mobxStores || {}, newProps, context) || {};\n      for (key in additionalProps) {\n        newProps[key] = additionalProps[key];\n      }\n\n      return createComponentVNode(\n        VNodeFlags.ComponentUnknown,\n        component,\n        newProps,\n        null,\n\n        isStateless(component) ? null : this.storeRef,\n      );\n    }\n  }\n\n  // Static fields from component should be visible on the generated Injector\n  hoistStaticProperties(Injector, component);\n\n  Injector.wrappedComponent = component;\n  Object.defineProperties(Injector, proxiedInjectorProps);\n\n  return Injector;\n}\n\nfunction grabStoresByName(storeNames: string[]) {\n  return function (baseStores, nextProps) {\n    for (let i = 0, len = storeNames.length; i < len; ++i) {\n      const storeName = storeNames[i];\n\n      if (!(storeName in nextProps)) {\n        // Development warning\n        if (process.env.NODE_ENV !== 'production') {\n          if (!(storeName in baseStores)) {\n            throw new Error(\n              \"MobX injector: Store '\" +\n                storeName +\n                \"' is not available! Make sure it is provided by some Provider\",\n            );\n          }\n        }\n\n        nextProps[storeName] = baseStores[storeName];\n      }\n    }\n    return nextProps;\n  };\n}\n\n/**\n * higher order component that injects stores to a child.\n * takes either a varargs list of strings, which are stores read from the context,\n * or a function that manually maps the available stores from the context to props:\n * storesToProps(mobxStores, props, context) => newProps\n */\n// TODO: Type\nexport function inject(...storeNames: string[]): <T>(target: T) => T;\nexport function inject(fn: Function): <T>(target: T) => T;\nexport function inject(\n  /* fn(stores, nextProps) or ...storeNames */ ...args\n): any {\n  let grabStoresFn;\n  if (typeof args[0] === 'function') {\n    grabStoresFn = args[0];\n\n    return function (componentClass) {\n      let injected = createStoreInjector(grabStoresFn, componentClass);\n      injected.isMobxInjector = false; // supress warning\n      // mark the Injector as observer, to make it react to expressions in `grabStoresFn`,\n      // see #111\n      injected = observer(injected);\n      injected.isMobxInjector = true; // restore warning\n      return injected;\n    };\n  } else {\n    const storeNames: any = [];\n    for (let i = 0; i < args.length; ++i) {\n      storeNames.push(args[i]);\n    }\n\n    grabStoresFn = grabStoresByName(storeNames);\n    return function (componentClass) {\n      return createStoreInjector(\n        grabStoresFn,\n        componentClass,\n        storeNames.join('-'),\n      );\n    };\n  }\n}\n"
  },
  {
    "path": "packages/inferno-mobx/src/observerPatch.ts",
    "content": "import { warning } from 'inferno-shared';\nimport { Reaction } from 'mobx';\nimport { type InfernoNode } from 'inferno';\n\ntype Render = (this, properties?, state?, context?) => InfernoNode;\n\ntype ObserverRender<R extends Render = Render> = R & { dispose: () => void };\n\nfunction makeObserverRender<R extends Render>(\n  update: () => void,\n  render: R,\n  name: string,\n): ObserverRender<R> {\n  const reactor = new Reaction(name, update);\n  const track = reactor.track.bind(reactor);\n  const observer = function (this, ...parameters: Parameters<typeof render>) {\n    let rendered: InfernoNode;\n    let caught;\n    track(() => {\n      try {\n        rendered = render.apply(this, parameters);\n      } catch (error) {\n        caught = error;\n      }\n    });\n    if (caught) {\n      throw caught;\n    } else {\n      return rendered;\n    }\n  } as ObserverRender<R>;\n  observer.dispose = reactor.dispose.bind(reactor);\n  return observer;\n}\n\ninterface Target {\n  readonly displayName?: string;\n  readonly forceUpdate: (callback?: () => void) => void;\n  render: Render;\n  componentWillUnmount?: () => void;\n}\n\n/**\n * Turns a class Component into a MobX observer.\n * @param clazz The constructor of the class to patch as a MobX observer.\n */\nexport function observerPatch<T extends Target, P, C>(\n  clazz: (new (p: P, c: C) => T) | (new (p: P) => T) | (new () => T),\n): void {\n  const proto = clazz.prototype as T;\n  if (process.env.NODE_ENV !== 'production') {\n    if (\n      (clazz as { readonly isMobxInjector?: boolean }).isMobxInjector === true\n    ) {\n      warning(\n        \"Mobx observerPatch: You are trying to use 'observerPatch' on a component that already has 'inject'. Please apply 'observerPatch' before applying 'inject'\",\n      );\n    } else if (\n      (clazz as { readonly isMobXReactObserver?: boolean })\n        .isMobXReactObserver === true\n    ) {\n      warning(\n        \"Mobx observerPatch: You are trying to use 'observerPatch' on a component that already has 'observer'. Please only apply one of 'observer' or 'observerPatch'\",\n      );\n    } else if (\n      (clazz as { readonly isMobXInfernoObserver?: boolean })\n        .isMobXInfernoObserver === true\n    ) {\n      warning(\n        \"Mobx observerPatch: You are trying to use 'observerPatch' on a component that already has 'observerPatch' applied. Please only apply once\",\n      );\n    }\n    (clazz as { isMobXInfernoObserver?: boolean }).isMobXInfernoObserver = true;\n  }\n  const base = proto.render;\n  const name = clazz.name;\n  proto.render = function (this: T, ...parameters) {\n    const update = this.forceUpdate.bind(this, undefined);\n    const render = makeObserverRender(\n      update,\n      base,\n      `${this.displayName || name}.render()`,\n    );\n    this.render = render;\n    return render.apply(this, parameters);\n  };\n  if (proto.componentWillUnmount) {\n    const unmount = proto.componentWillUnmount;\n    proto.componentWillUnmount = function (\n      this: T & { render: ObserverRender },\n    ) {\n      this.render.dispose();\n      this.render = base as ObserverRender;\n      unmount.call(this);\n    };\n  } else {\n    proto.componentWillUnmount = function (\n      this: T & { render: ObserverRender },\n    ) {\n      this.render.dispose();\n      this.render = base as ObserverRender;\n    };\n  }\n}\n"
  },
  {
    "path": "packages/inferno-mobx/src/observerWrap.ts",
    "content": "import {\n  _HI as normalizeRoot,\n  createComponentVNode,\n  type InfernoNode,\n  render,\n  type VNode,\n} from 'inferno';\nimport { Reaction } from 'mobx';\nimport { throwError, warning } from 'inferno-shared';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\ntype Render = (\n  properties?: any,\n  context?: Record<string, unknown>,\n) => InfernoNode;\n\nfunction callDispose({ dispose }: { readonly dispose: () => void }): void {\n  dispose();\n}\n\ninterface InnerProperties {\n  readonly context: unknown;\n  readonly dispose: () => void;\n  readonly props: unknown;\n  readonly self: VNode;\n  readonly track: (f: () => void) => void;\n}\n\nfunction innerVNode<T>(\n  type: (p: InnerProperties) => T,\n  properties: InnerProperties,\n): VNode {\n  const ref = {\n    onComponentDidUpdate: callDispose,\n    onComponentWillUnmount: properties.dispose,\n  };\n  if (process.env.NODE_ENV !== 'production') {\n    Object.freeze(properties);\n    Object.freeze(ref);\n  }\n  return createComponentVNode(\n    VNodeFlags.ComponentFunction,\n    type,\n    properties,\n    undefined,\n    ref,\n  );\n}\n\nfunction makeProxy(target: VNode): { $V: InfernoNode } {\n  return {\n    get $V() {\n      return target.children;\n    },\n    set $V(value) {\n      target.children = value;\n    },\n  };\n}\n\ntype UpdateHook = (this: RefType, prev: unknown, next: unknown) => void;\n\ninterface RefType {\n  readonly onComponentDidUpdate?: UpdateHook;\n  readonly onComponentWillUpdate?: UpdateHook;\n}\n\nfunction getUpdateHooks(\n  ref: RefType | null,\n  props: unknown,\n): Array<null | (() => void)> {\n  let onComponentDidUpdate = null;\n  let onComponentWillUpdate = null;\n  if (ref) {\n    if (ref.onComponentDidUpdate) {\n      onComponentDidUpdate = ref.onComponentDidUpdate.bind(ref, props, props);\n    }\n    if (ref.onComponentWillUpdate) {\n      onComponentWillUpdate = ref.onComponentWillUpdate.bind(ref, props, props);\n    }\n  }\n  return [onComponentDidUpdate, onComponentWillUpdate];\n}\n\nexport function observerWrap<T extends Render>(base: T): typeof base {\n  if (process.env.NODE_ENV !== 'production') {\n    if (typeof base !== 'function') {\n      throwError(\n        `observerWrap requires a function to wrap, got ${typeof base} instead`,\n      );\n    }\n    if (base.prototype?.render) {\n      throwError('observerWrap should not be applied to constructors.');\n    }\n    // @ts-expect-error there is no type for this\n    if (base.isMobXInfernoObserver) {\n      warning(\n        \"'observerWrap' was used on a component that already has 'observerWrap' applied. Please only apply once\",\n      );\n    }\n  }\n  function tracked({\n    context,\n    props,\n    self,\n    track,\n  }: InnerProperties): ReturnType<typeof base> {\n    let result;\n    let caught;\n    track(() => {\n      try {\n        result = base.call(self, props, context);\n      } catch (error) {\n        caught = error;\n      }\n    });\n    if (caught) {\n      throw caught;\n    }\n    return result;\n  }\n  function wrapper(this: VNode, props, context): VNode {\n    const [onComponentDidUpdate, onComponentWillUpdate] = getUpdateHooks(\n      this.ref,\n      props,\n    );\n    // eslint-disable-next-line prefer-const\n    let proxy;\n    const reaction = new Reaction(base.name, () => {\n      let next;\n      if (onComponentWillUpdate) {\n        onComponentWillUpdate();\n      }\n      reaction.track(() => {\n        next = normalizeRoot(base.call(this, props, context));\n      });\n      if (next) {\n        // indirectly call patch as inferno does not export patch\n        render(next, proxy, onComponentDidUpdate, context);\n      }\n    });\n    const inner = innerVNode(tracked, {\n      context,\n      dispose: reaction.dispose.bind(reaction),\n      props,\n      self: this,\n      track: reaction.track.bind(reaction),\n    });\n    proxy = makeProxy(inner);\n    return inner;\n  }\n  wrapper.defaultProps = (base as any).defaultProps;\n  wrapper.defaultHooks = (base as any).defaultHooks;\n  if (process.env.NODE_ENV !== 'production') {\n    wrapper.isMobXInfernoObserver = true;\n  }\n  return wrapper as any;\n}\n"
  },
  {
    "path": "packages/inferno-mobx/src/utils/EventEmitter.ts",
    "content": "export class EventEmitter {\n  public listeners: Array<(data: unknown) => void> = [];\n\n  public on(cb: (data: unknown) => void): () => void {\n    this.listeners.push(cb);\n    return () => {\n      const index = this.listeners.indexOf(cb);\n      if (index !== -1) {\n        this.listeners.splice(index, 1);\n      }\n    };\n  }\n\n  public emit(data: unknown): void {\n    const listeners = this.listeners;\n    for (let i = 0, len = listeners.length; i < len; ++i) {\n      listeners[i](data);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno-mobx/src/utils/utils.ts",
    "content": "export function isStateless(component: any): boolean {\n  return !component.prototype?.render;\n}\n"
  },
  {
    "path": "packages/inferno-redux/README.md",
    "content": "# inferno-redux\n\nInferno Redux is a [redux](https://github.com/reactjs/redux) library for [Inferno](https://github.com/infernojs/inferno).\n\nInferno Redux passes `context.store` value to each component.\n\n## Install\n\n```\nnpm install inferno-redux\n```\n\n## Contents\n\n- Provider\n- connect\n\n## Usage\n\nUsage of `inferno-redux` is similar to that of [react-redux](https://github.com/reactjs/react-redux).\nInspiration was taken from `react-redux` to provide Inferno with a similar API.\n\n```js\nimport { render } from 'inferno';\nimport { Router, Route, browserHistory } from 'inferno-router';\nimport { Provider } from 'inferno-redux';\nimport { createStore } from 'redux';\n\nconst store = createStore(function (state, action) {\n  switch (action.type) {\n    case 'CHANGE_NAME':\n      return {\n        name: action.name,\n      };\n    default:\n      return {\n        name: 'TOM',\n      };\n  }\n});\n\nclass App extends Component {\n  render() {\n    return <div>{this.props.children}</div>;\n  }\n}\n\nclass BasicComponent1 extends Component {\n  render() {\n    const store = this.context.store;\n    const state = store.getState();\n\n    const onClick = (e) => {\n      e.preventDefault();\n      store.dispatch({\n        type: 'CHANGE_NAME',\n        name: 'Jerry',\n      });\n    };\n\n    return (\n      <div className=\"basic\">\n        <a id=\"dispatch\" onClick={onClick}>\n          <span>Hello {state.name || 'Tom'}</span>\n        </a>\n      </div>\n    );\n  }\n}\n\nclass BasicComponent2 extends Component {\n  render() {\n    const store = this.context.store;\n    const state = store.getState();\n\n    return (\n      <div className=\"basic2\">\n        {state.name === 'Jerry' ? \"You're a mouse!\" : \"You're a cat!\"}\n      </div>\n    );\n  }\n}\n\nrender(\n  <Provider store={store}>\n    <Router history={browserHistory} component={App}>\n      <Route path=\"/next\" component={BasicComponent2} />\n      <Route path=\"/\" component={BasicComponent1} />\n    </Router>\n  </Provider>,\n  container,\n);\n```\n"
  },
  {
    "path": "packages/inferno-redux/__tests__/components/Provider.spec.js",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport { connect, Provider } from 'inferno-redux';\nimport { findRenderedVNodeWithType } from 'inferno-test-utils';\nimport { createStore } from 'redux';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\ndescribe('redux', () => {\n  let container;\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    render(null, container);\n    document.body.removeChild(container);\n  });\n\n  function renderIntoContainer(vNode) {\n    render(vNode, container);\n\n    if (vNode && vNode.flags & VNodeFlags.Component) {\n      return vNode.children;\n    }\n  }\n\n  describe('Provider', () => {\n    class Child extends Component {\n      render() {\n        return createElement('div', {});\n      }\n    }\n\n    it('should add the store to the child context', () => {\n      const store1 = createStore(() => ({}));\n      const store2 = createStore(() => ({}));\n\n      spyOn(console, 'error');\n\n      let tree = renderIntoContainer(\n        createElement(Provider, { store: store1 }, createElement(Child, {})),\n      );\n      expect(console.error).toHaveBeenCalledTimes(0);\n\n      let child = findRenderedVNodeWithType(tree, Child).children;\n      expect(child.context.store).toBe(store1);\n\n      tree = renderIntoContainer(\n        createElement(\n          Provider,\n          { store: store1 },\n          createElement(Provider, { store: store2 }, createElement(Child, {})),\n        ),\n      );\n\n      expect(console.error).toHaveBeenCalledTimes(0);\n\n      child = findRenderedVNodeWithType(tree, Child).children;\n      expect(child.context.store).toBe(store2);\n    });\n\n    it('should warn once when receiving a new store in props', () => {\n      const store1 = createStore((state = 10) => state + 1);\n      const store2 = createStore((state = 10) => state * 2);\n      const store3 = createStore((state = 10) => state * state);\n\n      class ProviderContainer extends Component {\n        constructor() {\n          super();\n          this.state = { store: store1 };\n        }\n\n        render() {\n          return (\n            <Provider store={this.state.store}>\n              <Child />\n            </Provider>\n          );\n        }\n      }\n\n      const vNode = <ProviderContainer />;\n      const container = renderIntoContainer(vNode);\n      const child = findRenderedVNodeWithType(container, Child).children;\n      expect(child.context.store.getState()).toEqual(11);\n\n      spyOn(console, 'error');\n      container.setState({ store: store2 });\n      renderIntoContainer(vNode);\n\n      expect(child.context.store.getState()).toEqual(11);\n      expect(console.error).toHaveBeenCalledTimes(1);\n      expect(console.error).toHaveBeenCalledWith(\n        '<Provider> does not support changing `store` on the fly.',\n      );\n\n      container.setState({ store: store3 });\n      renderIntoContainer(vNode);\n\n      expect(child.context.store.getState()).toEqual(11);\n      expect(console.error).toHaveBeenCalledTimes(1);\n    });\n\n    it('should handle subscriptions correctly when there is nested Providers', () => {\n      const reducer1 = (state = 2, action) =>\n        action.type === 'INC' ? state + 1 : state;\n      const reducer2 = (state = 5, action) =>\n        action.type === 'INC' ? state + 2 : state;\n\n      const innerStore = createStore(reducer1);\n      innerStore.__store_name__ = 'innerStore'; // for debugging\n      const innerMapStateToProps = jasmine.createSpy((state) => ({\n        count: state,\n      }));\n\n      const Inner = connect(innerMapStateToProps)(\n        class Inner extends Component {\n          render() {\n            return <div>{this.props.count}</div>;\n          }\n        },\n      );\n\n      const outerStore = createStore(reducer2);\n      outerStore.__store_name__ = 'outerStore'; // for debugging\n      const Outer = connect((state) => ({ count: state }))(\n        class Outer extends Component {\n          render() {\n            return (\n              <Provider store={innerStore}>\n                <Inner />\n              </Provider>\n            );\n          }\n        },\n      );\n\n      renderIntoContainer(\n        <Provider store={outerStore}>\n          <Outer />\n        </Provider>,\n      );\n      expect(innerMapStateToProps.calls.count()).toEqual(1);\n\n      innerStore.dispatch({ type: 'INC' });\n      expect(innerMapStateToProps.calls.count()).toEqual(2);\n    });\n\n    it('should pass state consistently to mapState', () => {\n      const stringBuilder = (prev = '', action) =>\n        action.type === 'APPEND' ? prev + action.payload : prev;\n\n      const store = createStore(stringBuilder);\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      let childMapStateInvokes = 0;\n\n      const ChildContainer = connect((state, parentProps) => {\n        childMapStateInvokes++;\n        // The state from parent props should always be consistent with the current state\n        expect(state).toBe(parentProps.parentState);\n        return {};\n      })(\n        class ChildContainer extends Component {\n          render() {\n            return <div />;\n          }\n        },\n      );\n\n      const Container = connect((state) => ({ state }), null, null, {\n        withRef: true,\n      })(\n        class Container extends Component {\n          emitChange() {\n            store.dispatch({ type: 'APPEND', payload: 'b' });\n          }\n\n          render() {\n            // NOTE: This should really be onClick not onclick. More bugs in inferno event delegation?\n            return (\n              <div>\n                <button\n                  ref={(btn) => {\n                    this.button = btn;\n                  }}\n                  onClick={this.emitChange.bind(this)}\n                >\n                  change\n                </button>\n                <ChildContainer parentState={this.props.state} />\n              </div>\n            );\n          }\n        },\n      );\n\n      const vNode = (\n        <Provider store={store}>\n          <Container />\n        </Provider>\n      );\n      const tree = renderIntoContainer(vNode);\n\n      expect(childMapStateInvokes).toEqual(1);\n\n      // The store state stays consistent when setState calls are batched\n      store.dispatch({ type: 'APPEND', payload: 'c' });\n      renderIntoContainer(vNode);\n      expect(childMapStateInvokes).toEqual(2);\n\n      // setState calls DOM handlers are batched\n      const container = findRenderedVNodeWithType(tree, Container).children;\n      const node = container.getWrappedInstance().button;\n      node.click();\n      renderIntoContainer(vNode);\n      expect(childMapStateInvokes).toEqual(3);\n\n      // Provider uses unstable_batchedUpdates() under the hood\n      store.dispatch({ type: 'APPEND', payload: 'd' });\n      renderIntoContainer(vNode);\n      expect(childMapStateInvokes).toEqual(4);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-redux/__tests__/components/Provider.typings.tsx",
    "content": "import { type AnyAction, createStore } from 'redux';\n\nimport { render } from 'inferno';\nimport { Provider } from 'inferno-redux';\n\ndescribe('Component typings', () => {\n  // Basic app state for typing reducer arguments.\n  interface AppState {\n    posts?: string[];\n  }\n\n  let container: Element;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    document.body.removeChild(container);\n  });\n\n  it('should accept store with default action type', () => {\n    const rootReducer = (state: AppState = {}, _: AnyAction) => {\n      return state;\n    };\n\n    const store = createStore(rootReducer);\n\n    render(<Provider store={store}></Provider>, container);\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should accept store with custom action type', () => {\n    // Some custom action interfaces\n    interface FetchPostsAction {\n      type: 'FETCH_ACTION';\n      data: string;\n    }\n\n    interface ReceivePostsAction {\n      type: 'RECEIVE_ACTION';\n      data: string;\n    }\n\n    type MyAction = FetchPostsAction | ReceivePostsAction;\n\n    const rootReducer = (state: AppState = {}, _: MyAction) => state;\n    const store = createStore(rootReducer);\n\n    render(<Provider store={store}></Provider>, container);\n    expect(container.innerHTML).toBe('');\n  });\n\n  it('should accept children', () => {\n    const HelloComponent = () => <p>Hello my friends!</p>;\n\n    const store = createStore(() => ({}));\n\n    render(\n      <Provider store={store}>\n        <h1>Hello Page</h1>\n        <HelloComponent />\n        <p>Another greetings!</p>\n      </Provider>,\n      container,\n    );\n    expect(container.innerHTML).toBe(\n      '<h1>Hello Page</h1><p>Hello my friends!</p><p>Another greetings!</p>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-redux/__tests__/components/connect.spec.js",
    "content": "import { Component, render as _render, rerender } from 'inferno';\nimport { connect } from 'inferno-redux';\nimport { findRenderedVNodeWithType, Wrapper } from 'inferno-test-utils';\nimport { createStore } from 'redux';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\ndescribe('Inferno', () => {\n  // IE does not support function names so error messages are different\n  const testFunction = function testFunction() {};\n  const supportFnName = testFunction.name === 'testFunction';\n  const unmountDOM = (elm) => render(null, elm);\n  let container;\n\n  function render(vNode, container, cb) {\n    _render(vNode, container, cb);\n\n    if (vNode && vNode.flags & VNodeFlags.Component) {\n      return vNode.children;\n    }\n  }\n\n  beforeEach(() => {\n    rerender();\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    render(null, container);\n    document.body.removeChild(container);\n  });\n\n  function renderToContainer(vNode) {\n    return render(vNode, container);\n  }\n\n  describe('redux', () => {\n    class Passthrough extends Component {\n      render() {\n        return <div />;\n      }\n    }\n\n    class ProviderMock extends Component {\n      getChildContext() {\n        return { store: this.props.store };\n      }\n\n      render() {\n        return this.props.children;\n      }\n    }\n\n    class ContextBoundStore {\n      constructor(reducer) {\n        this.reducer = reducer;\n        this.listeners = [];\n        this.state = undefined;\n        this.dispatch({});\n      }\n\n      getState() {\n        return this.state;\n      }\n\n      subscribe(listener) {\n        let live = true;\n        const call = (...args) => {\n          if (live) {\n            listener(...args);\n          }\n        };\n        this.listeners.push(call);\n        return () => {\n          live = false;\n          this.listeners = this.listeners.filter((c) => c !== call);\n        };\n      }\n\n      dispatch(action) {\n        this.state = this.reducer(this.state, action);\n        for (const l of this.listeners) {\n          l();\n        }\n        return action;\n      }\n    }\n\n    const stringBuilder = (prev = '', action) =>\n      action.type === 'APPEND' ? prev + action.payload : prev;\n\n    const renderWithBadConnect = (Component) => {\n      const store = createStore(() => ({}));\n\n      try {\n        renderToContainer(\n          <ProviderMock store={store}>\n            <Component pass=\"through\" />\n          </ProviderMock>,\n        );\n\n        return null;\n      } catch (e) {\n        return e.message;\n      }\n    };\n\n    it('should receive the store in the context', () => {\n      const store = createStore(() => ({}));\n\n      const Container = connect()(\n        class Container extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const tree = renderToContainer(\n        <ProviderMock store={store}>\n          <Container pass=\"through\" />\n        </ProviderMock>,\n      );\n\n      const container = findRenderedVNodeWithType(tree, Container).children;\n      expect(container.context.store).toBe(store);\n    });\n\n    it('should pass state and props to the given component', () => {\n      const store = createStore(() => ({\n        foo: 'bar',\n        baz: 42,\n        hello: 'world',\n      }));\n\n      const Container = connect(({ foo, baz }) => ({ foo, baz }))(\n        class Container extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const tree = renderToContainer(\n        <ProviderMock store={store}>\n          <Container pass=\"through\" baz={50} />\n        </ProviderMock>,\n      );\n\n      const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n      expect(stub.props.pass).toBe('through');\n      expect(stub.props.foo).toBe('bar');\n      expect(stub.props.baz).toBe(42);\n      expect(stub.props.hello).toBe(undefined);\n      findRenderedVNodeWithType(tree, Container);\n    });\n\n    it('should subscribe class components to the store changes', () => {\n      const store = createStore(stringBuilder);\n\n      const Container = connect((state) => ({ string: state }))(\n        class Container extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const vNode = (\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>\n      );\n      const tree = renderToContainer(vNode);\n\n      const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n      expect(stub.props.string).toBe('');\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      renderToContainer(vNode);\n      expect(stub.props.string).toBe('a');\n\n      store.dispatch({ type: 'APPEND', payload: 'b' });\n      renderToContainer(vNode);\n      expect(stub.props.string).toBe('ab');\n    });\n\n    it('should subscribe pure function components to the store changes', () => {\n      const store = createStore(stringBuilder);\n\n      const Container = connect((state) => ({\n        string: state,\n      }))(function Container(props) {\n        return <Passthrough {...props} />;\n      });\n\n      const vNode = (\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>\n      );\n      const tree = renderToContainer(vNode);\n\n      const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n      expect(stub.props.string).toBe('');\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      renderToContainer(vNode);\n      expect(stub.props.string).toBe('a');\n\n      store.dispatch({ type: 'APPEND', payload: 'b' });\n      renderToContainer(vNode);\n      expect(stub.props.string).toBe('ab');\n    });\n\n    it(\"should retain the store's context\", () => {\n      const store = new ContextBoundStore(stringBuilder);\n\n      const Container = connect((state) => ({\n        string: state,\n      }))(function Container(props) {\n        return <Passthrough {...props} />;\n      });\n\n      const spy = spyOn(console, 'error');\n\n      const vNode = (\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>\n      );\n      const tree = renderToContainer(vNode);\n\n      expect(spy.calls.count()).toBe(0);\n\n      const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n      expect(stub.props.string).toBe('');\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      renderToContainer(vNode);\n      expect(stub.props.string).toBe('a');\n    });\n\n    it('should handle dispatches before componentDidMount', (done) => {\n      const store = createStore(stringBuilder);\n\n      const Container = connect((state) => ({ string: state }))(\n        class Container extends Component {\n          componentDidMount() {\n            store.dispatch({ type: 'APPEND', payload: 'a' });\n          }\n\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const tree = renderToContainer(\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>,\n      );\n\n      setTimeout(() => {\n        const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n        expect(stub.props.string).toBe('a');\n        done();\n      }, 20);\n    });\n\n    it('should handle additional prop changes in addition to slice', () => {\n      const store = createStore(() => ({\n        foo: 'bar',\n      }));\n\n      const ConnectContainer = connect((state) => state)(\n        class ConnectContainer extends Component {\n          render() {\n            return <Passthrough {...this.props} pass={this.props.bar.baz} />;\n          }\n        },\n      );\n\n      class Container extends Component {\n        constructor() {\n          super();\n          this.state = {\n            bar: {\n              baz: '',\n            },\n          };\n        }\n\n        componentDidMount() {\n          const newBar = {};\n\n          for (const key in this.state.bar) {\n            newBar[key] = this.state.bar[key];\n          }\n          newBar.baz = 'through';\n          this.setState({\n            bar: newBar,\n          });\n        }\n\n        render() {\n          return (\n            <ProviderMock store={store}>\n              <ConnectContainer bar={this.state.bar} />\n            </ProviderMock>\n          );\n        }\n      }\n\n      const vNode = <Container />;\n      const tree = renderToContainer(vNode);\n      const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n\n      renderToContainer(vNode);\n\n      rerender();\n\n      expect(stub.props.foo).toBe('bar');\n      expect(stub.props.pass).toBe('through');\n    });\n\n    it('should handle unexpected prop changes with forceUpdate()', (done) => {\n      const store = createStore(() => ({}));\n\n      const ConnectContainer = connect((state) => state)(\n        class ConnectContainer extends Component {\n          render() {\n            return <Passthrough {...this.props} pass={this.props.bar} />;\n          }\n        },\n      );\n\n      class Container extends Component {\n        constructor() {\n          super();\n          this.baz = 'baz';\n        }\n\n        componentDidMount() {\n          this.bar = 'foo';\n          this.forceUpdate();\n          this.c.forceUpdate();\n        }\n\n        render() {\n          return (\n            <ProviderMock store={store}>\n              <ConnectContainer\n                bar={this.bar}\n                ref={(c) => {\n                  this.c = c;\n                }}\n              />\n            </ProviderMock>\n          );\n        }\n      }\n\n      const tree = renderToContainer(<Container />);\n\n      setTimeout(() => {\n        const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n        expect(stub.props.bar).toBe('foo');\n        done();\n      }, 20);\n    });\n\n    it('should remove undefined props', () => {\n      const store = createStore(() => {});\n      let props = { x: true };\n      let container;\n\n      const ConnectContainer = connect(\n        () => ({}),\n        () => ({}),\n      )(\n        class ConnectContainer extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      class HolderContainer extends Component {\n        render() {\n          return <ConnectContainer {...props} />;\n        }\n      }\n\n      renderToContainer(\n        <ProviderMock store={store}>\n          <HolderContainer\n            ref={(instance) => {\n              container = instance;\n            }}\n          />\n        </ProviderMock>,\n      );\n\n      const propsBefore = {\n        ...findRenderedVNodeWithType(container, Passthrough).children.props,\n      };\n\n      props = {};\n      container.forceUpdate();\n\n      const propsAfter = {\n        ...findRenderedVNodeWithType(container, Passthrough).children.props,\n      };\n\n      expect(propsBefore.x).toBe(true);\n      expect('x' in propsAfter).toBe(false);\n    });\n\n    it('should remove undefined props without mapDispatch', () => {\n      const store = createStore(() => ({}));\n      let props = { x: true };\n      let container;\n\n      const ConnectContainer = connect(() => ({}))(\n        class ConnectContainer extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      class HolderContainer extends Component {\n        render() {\n          return <ConnectContainer {...props} />;\n        }\n      }\n\n      renderToContainer(\n        <ProviderMock store={store}>\n          <HolderContainer\n            ref={(instance) => {\n              container = instance;\n            }}\n          />\n        </ProviderMock>,\n      );\n\n      const propsBefore = {\n        ...findRenderedVNodeWithType(container, Passthrough).children.props,\n      };\n\n      props = {};\n      container.forceUpdate();\n\n      const propsAfter = {\n        ...findRenderedVNodeWithType(container, Passthrough).children.props,\n      };\n\n      expect(propsBefore.x).toBe(true);\n      expect('x' in propsAfter).toBe(false);\n    });\n\n    it('should ignore deep mutations in props', () => {\n      const store = createStore(() => ({\n        foo: 'bar',\n      }));\n\n      const ConnectContainer = connect((state) => state)(\n        class ConnectContainer extends Component {\n          render() {\n            return <Passthrough {...this.props} pass={this.props.bar.baz} />;\n          }\n        },\n      );\n\n      class Container extends Component {\n        constructor() {\n          super();\n          this.state = {\n            bar: {\n              baz: '',\n            },\n          };\n        }\n\n        componentDidMount() {\n          // Simulate deep object mutation\n          const bar = this.state.bar;\n          bar.baz = 'through';\n          this.setState({\n            bar,\n          });\n        }\n\n        render() {\n          return (\n            <ProviderMock store={store}>\n              <ConnectContainer bar={this.state.bar} />\n            </ProviderMock>\n          );\n        }\n      }\n\n      const tree = renderToContainer(<Container />);\n      const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n      expect(stub.props.foo).toBe('bar');\n      expect(stub.props.pass).toBe('');\n    });\n\n    it('should allow for merge to incorporate state and prop changes', (done) => {\n      const store = createStore(stringBuilder);\n\n      const doSomething = (thing) => ({\n        type: 'APPEND',\n        payload: thing,\n      });\n\n      const Container = connect(\n        (state) => ({ stateThing: state }),\n        (dispatch) => ({\n          doSomething: (whatever) => dispatch(doSomething(whatever)),\n        }),\n        (stateProps, actionProps, parentProps) => ({\n          ...stateProps,\n          ...actionProps,\n          mergedDoSomething(thing) {\n            const seed = stateProps.stateThing === '' ? 'HELLO ' : '';\n            actionProps.doSomething(seed + thing + parentProps.extra);\n          },\n        }),\n      )(\n        class Container extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      class OuterContainer extends Component {\n        constructor() {\n          super();\n          this.state = { extra: 'z' };\n        }\n\n        render() {\n          return (\n            <ProviderMock store={store}>\n              <Container extra={this.state.extra} />\n            </ProviderMock>\n          );\n        }\n      }\n\n      const outerStub = render(\n        <OuterContainer />,\n        document.createElement('div'),\n      );\n      const stub = findRenderedVNodeWithType(outerStub, Passthrough).children;\n      expect(stub.props.stateThing).toBe('');\n      stub.props.mergedDoSomething('a');\n      outerStub.setState({}, () => {\n        expect(stub.props.stateThing).toBe('HELLO az');\n\n        stub.props.mergedDoSomething('b');\n        outerStub.setState({}, () => {\n          expect(stub.props.stateThing).toBe('HELLO azbz');\n\n          outerStub.setState({ extra: 'Z' });\n          outerStub.setState({}, () => {\n            stub.props.mergedDoSomething('c');\n            outerStub.setState({}, () => {\n              expect(stub.props.stateThing).toBe('HELLO azbzcZ');\n\n              done();\n            });\n          });\n        });\n      });\n    });\n\n    it('should merge actionProps into WrappedComponent', () => {\n      const store = createStore(() => ({\n        foo: 'bar',\n      }));\n\n      const Container = connect(\n        (state) => state,\n        (dispatch) => ({ dispatch }),\n      )(\n        class Container extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const tree = renderToContainer(\n        <ProviderMock store={store}>\n          <Container pass=\"through\" />\n        </ProviderMock>,\n      );\n\n      const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n      expect(stub.props.dispatch).toBe(store.dispatch);\n      expect(stub.props.foo).toBe('bar');\n      expect(\n        () => findRenderedVNodeWithType(tree, Container).children,\n      ).not.toThrow();\n      const decorated = findRenderedVNodeWithType(tree, Container).children;\n      expect(decorated.isSubscribed()).toBe(true);\n    });\n\n    it('should not invoke mapState when props change if it only has one argument', () => {\n      const store = createStore(stringBuilder);\n\n      let invocationCount = 0;\n\n      const WithoutProps = connect((_arg1) => {\n        invocationCount++;\n        return {};\n      })(\n        class WithoutProps extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      class OuterComponent extends Component {\n        constructor() {\n          super();\n          this.state = { foo: 'FOO' };\n        }\n\n        setFoo(foo) {\n          this.setState({ foo });\n        }\n\n        render() {\n          return (\n            <div>\n              <WithoutProps {...this.state} />\n            </div>\n          );\n        }\n      }\n\n      let outerComponent;\n      renderToContainer(\n        <ProviderMock store={store}>\n          <OuterComponent\n            ref={(c) => {\n              outerComponent = c;\n            }}\n          />\n        </ProviderMock>,\n      );\n\n      outerComponent.setFoo('BAR');\n      outerComponent.setFoo('DID');\n\n      expect(invocationCount).toBe(1);\n    });\n\n    it('should invoke mapState every time props are changed if it has zero arguments', () => {\n      const store = createStore(stringBuilder);\n\n      let invocationCount = 0;\n\n      const WithoutProps = connect(() => {\n        invocationCount++;\n        return {};\n      })(\n        class WithoutProps extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      class OuterComponent extends Component {\n        constructor() {\n          super();\n          this.state = { foo: 'FOO' };\n        }\n\n        setFoo(foo) {\n          this.setState({ foo });\n        }\n\n        render() {\n          return (\n            <div>\n              <WithoutProps {...this.state} />\n            </div>\n          );\n        }\n      }\n\n      let outerComponent;\n      const vNode = (\n        <ProviderMock store={store}>\n          <OuterComponent\n            ref={(c) => {\n              outerComponent = c;\n            }}\n          />\n        </ProviderMock>\n      );\n      renderToContainer(vNode);\n\n      outerComponent.setFoo('BAR');\n      renderToContainer(vNode);\n      outerComponent.setFoo('DID');\n      renderToContainer(vNode);\n      expect(invocationCount).toBe(3);\n    });\n\n    it('should invoke mapState every time props are changed if it has a second argument', () => {\n      const store = createStore(stringBuilder);\n\n      let propsPassedIn;\n      let invocationCount = 0;\n\n      const WithoutProps = connect((_state, props) => {\n        invocationCount++;\n        propsPassedIn = props;\n        return {};\n      })(\n        class WithoutProps extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      class OuterComponent extends Component {\n        constructor() {\n          super();\n          this.state = { foo: 'FOO' };\n        }\n\n        setFoo(foo) {\n          this.setState({ foo });\n        }\n\n        render() {\n          return (\n            <div>\n              <WithoutProps {...this.state} />\n            </div>\n          );\n        }\n      }\n\n      let outerComponent;\n      const vNode = (\n        <ProviderMock store={store}>\n          <OuterComponent\n            ref={(c) => {\n              outerComponent = c;\n            }}\n          />\n        </ProviderMock>\n      );\n      renderToContainer(vNode);\n\n      outerComponent.setFoo('BAR');\n      renderToContainer(vNode);\n      outerComponent.setFoo('BAZ');\n      renderToContainer(vNode);\n\n      expect(invocationCount).toBe(3);\n      expect(propsPassedIn).toEqual({\n        foo: 'BAZ',\n      });\n    });\n\n    it('should not invoke mapDispatch when props change if it only has one argument', () => {\n      const store = createStore(stringBuilder);\n\n      let invocationCount = 0;\n\n      const WithoutProps = connect(null, (_arg1) => {\n        invocationCount++;\n        return {};\n      })(\n        class WithoutProps extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      class OuterComponent extends Component {\n        constructor() {\n          super();\n          this.state = { foo: 'FOO' };\n        }\n\n        setFoo(foo) {\n          this.setState({ foo });\n        }\n\n        render() {\n          return (\n            <div>\n              <WithoutProps {...this.state} />\n            </div>\n          );\n        }\n      }\n\n      let outerComponent;\n      renderToContainer(\n        <ProviderMock store={store}>\n          <OuterComponent\n            ref={(c) => {\n              outerComponent = c;\n            }}\n          />\n        </ProviderMock>,\n      );\n\n      outerComponent.setFoo('BAR');\n      outerComponent.setFoo('DID');\n\n      expect(invocationCount).toBe(1);\n    });\n\n    it('should invoke mapDispatch every time props are changed if it has zero arguments', () => {\n      const store = createStore(stringBuilder);\n\n      let invocationCount = 0;\n\n      const WithoutProps = connect(null, () => {\n        invocationCount++;\n        return {};\n      })(\n        class WithoutProps extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      class OuterComponent extends Component {\n        constructor() {\n          super();\n          this.state = { foo: 'FOO' };\n        }\n\n        setFoo(foo) {\n          this.setState({ foo });\n        }\n\n        render() {\n          return (\n            <div>\n              <WithoutProps {...this.state} />\n            </div>\n          );\n        }\n      }\n\n      let outerComponent;\n      const vNode = (\n        <ProviderMock store={store}>\n          <OuterComponent\n            ref={(c) => {\n              outerComponent = c;\n            }}\n          />\n        </ProviderMock>\n      );\n      renderToContainer(vNode);\n\n      outerComponent.setFoo('BAR');\n      renderToContainer(vNode);\n      outerComponent.setFoo('DID');\n      renderToContainer(vNode);\n      expect(invocationCount).toBe(3);\n    });\n\n    it('should invoke mapDispatch every time props are changed if it has a second argument', () => {\n      const store = createStore(stringBuilder);\n\n      let propsPassedIn;\n      let invocationCount = 0;\n\n      const WithoutProps = connect(null, (_state, props) => {\n        invocationCount++;\n        propsPassedIn = props;\n        return {};\n      })(\n        class WithoutProps extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      class OuterComponent extends Component {\n        constructor() {\n          super();\n          this.state = { foo: 'FOO' };\n        }\n\n        setFoo(foo) {\n          this.setState({ foo });\n        }\n\n        render() {\n          return (\n            <div>\n              <WithoutProps {...this.state} />\n            </div>\n          );\n        }\n      }\n\n      let outerComponent;\n      const vNode = (\n        <ProviderMock store={store}>\n          <OuterComponent\n            ref={(c) => {\n              outerComponent = c;\n            }}\n          />\n        </ProviderMock>\n      );\n      renderToContainer(vNode);\n\n      outerComponent.setFoo('BAR');\n      renderToContainer(vNode);\n      outerComponent.setFoo('BAZ');\n      renderToContainer(vNode);\n\n      expect(invocationCount).toBe(3);\n      expect(propsPassedIn).toEqual({\n        foo: 'BAZ',\n      });\n    });\n\n    it('should pass dispatch and avoid subscription if arguments are falsy', () => {\n      const store = createStore(() => ({\n        foo: 'bar',\n      }));\n\n      const runCheck = (...connectArgs) => {\n        const Container = connect(...connectArgs)(\n          class Container extends Component {\n            render() {\n              return <Passthrough {...this.props} />;\n            }\n          },\n        );\n\n        const vNode = (\n          <ProviderMock store={store}>\n            <Container pass=\"through\" />\n          </ProviderMock>\n        );\n        const tree = renderToContainer(vNode);\n\n        const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n        expect(stub.props.dispatch).toBe(store.dispatch);\n        expect(stub.props.foo).toBeUndefined();\n        expect(stub.props.pass).toBe('through');\n        expect(\n          () => findRenderedVNodeWithType(tree, Container).children,\n        ).not.toThrow();\n\n        const decorated = findRenderedVNodeWithType(tree, Container).children;\n        expect(decorated.isSubscribed()).toBe(false);\n      };\n\n      runCheck();\n      runCheck(null, null, null);\n      runCheck(false, false, false);\n    });\n\n    it('should unsubscribe before unmounting', () => {\n      const store = createStore(stringBuilder);\n      const subscribe = store.subscribe;\n\n      // Keep track of unsubscribe by wrapping subscribe()\n      let unsubscribeCalls = 0;\n      store.subscribe = (listener) => {\n        const unsubscribe = subscribe(listener);\n        return () => {\n          unsubscribeCalls++;\n          return unsubscribe();\n        };\n      };\n\n      const Container = connect(\n        (state) => ({ string: state }),\n        (dispatch) => ({ dispatch }),\n      )(\n        class Container extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const div = document.createElement('div');\n      render(\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>,\n        div,\n      );\n\n      expect(unsubscribeCalls).toBe(0);\n      unmountDOM(div);\n      expect(unsubscribeCalls).toBe(1);\n    });\n\n    it('should not attempt to set state after unmounting', () => {\n      const store = createStore(stringBuilder);\n      let mapStateToPropsCalls = 0;\n\n      const Container = connect(\n        () => ({ calls: ++mapStateToPropsCalls }),\n        (dispatch) => ({ dispatch }),\n      )(\n        class Container extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const div = document.createElement('div');\n      store.subscribe(() => {\n        unmountDOM(div);\n      });\n      render(\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>,\n        div,\n      );\n\n      expect(mapStateToPropsCalls).toBe(1);\n      const spy = spyOn(console, 'error');\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      expect(spy.calls.count()).toBe(0);\n      expect(mapStateToPropsCalls).toBe(1);\n    });\n\n    it('should not attempt to notify unmounted child of state change', () => {\n      class ProviderMockTest extends Component {\n        getChildContext() {\n          return { store: this.props.store };\n        }\n\n        render() {\n          return this.props.children;\n        }\n      }\n\n      const store = createStore(stringBuilder);\n\n      const App = connect((state) => ({ hide: state === 'AB' }))(\n        class App extends Component {\n          getDisplayName() {\n            return 'App';\n          }\n\n          render() {\n            return this.props.hide ? null : <Container />;\n          }\n        },\n      );\n\n      const Container = connect((state) => ({ state }))(\n        class Container extends Component {\n          getDisplayName() {\n            return 'Container';\n          }\n\n          componentWillReceiveProps(nextProps) {\n            if (nextProps.state === 'A') {\n              store.dispatch({ type: 'APPEND', payload: 'B' });\n            }\n          }\n\n          render() {\n            return null;\n          }\n        },\n      );\n\n      const div = document.createElement('div');\n      render(\n        <ProviderMockTest store={store}>\n          <App />\n        </ProviderMockTest>,\n        div,\n      );\n\n      try {\n        store.dispatch({ type: 'APPEND', payload: 'A' });\n      } finally {\n        unmountDOM(div);\n      }\n    });\n\n    it('should not attempt to set state after unmounting nested components', () => {\n      const store = createStore(() => ({}));\n      let mapStateToPropsCalls = 0;\n\n      let linkA;\n      let linkB;\n\n      let App = ({ children, setLocation }) => {\n        const onClick = (to) => (event) => {\n          event.preventDefault();\n          setLocation(to);\n        };\n\n        return (\n          <div>\n            <a\n              href=\"#\"\n              onClick={onClick('a')}\n              ref={(c) => {\n                linkA = c;\n              }}\n            >\n              A\n            </a>\n            <a\n              href=\"#\"\n              onClick={onClick('b')}\n              ref={(c) => {\n                linkB = c;\n              }}\n            >\n              B\n            </a>\n            {children}\n          </div>\n        );\n      };\n      App = connect(() => ({}))(App);\n\n      let A = () => <h1>A</h1>;\n      A = connect(() => ({ calls: ++mapStateToPropsCalls }))(A);\n\n      const B = () => <h1>B</h1>;\n\n      class RouterMock extends Component {\n        constructor(...args) {\n          super(...args);\n          this.state = { location: { pathname: 'a' } };\n          this.setLocation = this.setLocation.bind(this);\n        }\n\n        setLocation(pathname) {\n          store.dispatch({ type: 'TEST' });\n          this.setState({ location: { pathname } });\n        }\n\n        getChildComponent(location) {\n          switch (location) {\n            case 'a':\n              return <A />;\n            case 'b':\n              return <B />;\n            default:\n              throw new Error('Unknown location: ' + location);\n          }\n        }\n\n        render() {\n          return (\n            <App setLocation={this.setLocation}>\n              {this.getChildComponent(this.state.location.pathname)}\n            </App>\n          );\n        }\n      }\n\n      let wrapper;\n      const div = document.createElement('div');\n      document.body.appendChild(div);\n      const vNode = (\n        <Wrapper\n          ref={(w) => {\n            wrapper = w;\n          }}\n        >\n          <ProviderMock store={store}>\n            <RouterMock />\n          </ProviderMock>\n        </Wrapper>\n      );\n      render(vNode, div);\n\n      const spy = spyOn(console, 'error');\n      expect(mapStateToPropsCalls).toBe(1);\n      linkA.click();\n      render(vNode, div);\n      expect(mapStateToPropsCalls).toBe(2);\n      linkB.click();\n      render(vNode, div);\n\n      expect(mapStateToPropsCalls).toBe(3);\n      linkB.click();\n      render(vNode, div);\n\n      expect(spy.calls.count()).toBe(0);\n\n      unmountDOM(div);\n      document.body.removeChild(div);\n      expect(mapStateToPropsCalls).toBe(3);\n    });\n\n    it('should not attempt to set state when dispatching in componentWillUnmount', () => {\n      const store = createStore(stringBuilder);\n      let mapStateToPropsCalls = 0;\n\n      const Container = connect(\n        (state) => ({ calls: mapStateToPropsCalls++ }),\n        (dispatch) => ({ dispatch }),\n      )(\n        class Container extends Component {\n          componentWillUnmount() {\n            this.props.dispatch({ type: 'APPEND', payload: 'a' });\n          }\n\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const div = document.createElement('div');\n      render(\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>,\n        div,\n      );\n\n      expect(mapStateToPropsCalls).toBe(1);\n\n      const spy = spyOn(console, 'error');\n\n      unmountDOM(div);\n\n      expect(spy.calls.count()).toBe(0);\n\n      expect(mapStateToPropsCalls).toBe(1);\n    });\n\n    it('should shallowly compare the selected state to prevent unnecessary updates', () => {\n      const store = createStore(stringBuilder);\n      let renderCallCount = 0;\n\n      const Container = connect(\n        (state) => ({ string: state }),\n        (dispatch) => ({ dispatch }),\n      )(\n        class Container extends Component {\n          render() {\n            const { string } = this.props;\n\n            renderCallCount++;\n            return <Passthrough string={string} />;\n          }\n        },\n      );\n\n      const vNode = (\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>\n      );\n      const tree = renderToContainer(vNode);\n\n      const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n      expect(renderCallCount).toBe(1);\n      expect(stub.props.string).toBe('');\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      renderToContainer(vNode);\n      expect(renderCallCount).toBe(2);\n      store.dispatch({ type: 'APPEND', payload: 'b' });\n      renderToContainer(vNode);\n      expect(renderCallCount).toBe(3);\n      store.dispatch({ type: 'APPEND', payload: '' });\n      renderToContainer(vNode);\n      expect(renderCallCount).toBe(3);\n    });\n\n    it('should shallowly compare the merged state to prevent unnecessary updates', () => {\n      const store = createStore(stringBuilder);\n      let renderCallCount = 0;\n\n      const Container = connect(\n        (state) => ({ string: state }),\n        (dispatch) => ({ dispatch }),\n        (stateProps, dispatchProps, parentProps) => ({\n          ...dispatchProps,\n          ...stateProps,\n          ...parentProps,\n        }),\n      )(\n        class Container extends Component {\n          render() {\n            const { string, pass } = this.props;\n\n            renderCallCount++;\n            return (\n              <Passthrough string={string} pass={pass} passVal={pass.val} />\n            );\n          }\n        },\n      );\n\n      class Root extends Component {\n        constructor(props) {\n          super(props);\n          this.state = { pass: '' };\n        }\n\n        render() {\n          return (\n            <ProviderMock store={store}>\n              <Container pass={this.state.pass} />\n            </ProviderMock>\n          );\n        }\n      }\n\n      const vNode = <Root />;\n      const rootStub = renderToContainer(vNode);\n      const stub = findRenderedVNodeWithType(rootStub, Passthrough).children;\n\n      expect(renderCallCount).toBe(1);\n      expect(stub.props.string).toBe('');\n      expect(stub.props.pass).toBe('');\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      renderToContainer(vNode);\n      expect(renderCallCount).toBe(2);\n      expect(stub.props.string).toBe('a');\n      expect(stub.props.pass).toBe('');\n\n      rootStub.setState({ pass: '' });\n      renderToContainer(vNode);\n      expect(renderCallCount).toBe(2);\n      expect(stub.props.string).toBe('a');\n      expect(stub.props.pass).toBe('');\n\n      rootStub.setState({ pass: 'through' });\n      renderToContainer(vNode);\n      expect(renderCallCount).toBe(3);\n      expect(stub.props.string).toBe('a');\n      expect(stub.props.pass).toBe('through');\n\n      rootStub.setState({ pass: 'through' });\n      renderToContainer(vNode);\n      expect(renderCallCount).toBe(3);\n      expect(stub.props.string).toBe('a');\n      expect(stub.props.pass).toBe('through');\n\n      const obj = { prop: 'val' };\n      rootStub.setState({ pass: obj });\n      renderToContainer(vNode);\n      expect(renderCallCount).toBe(4);\n      expect(stub.props.string).toBe('a');\n      expect(stub.props.pass).toBe(obj);\n\n      rootStub.setState({ pass: obj });\n      renderToContainer(vNode);\n      expect(renderCallCount).toBe(4);\n      expect(stub.props.string).toBe('a');\n      expect(stub.props.pass).toBe(obj);\n\n      const obj2 = { ...obj, val: 'otherval' };\n      rootStub.setState({ pass: obj2 });\n      renderToContainer(vNode);\n      expect(renderCallCount).toBe(5);\n      expect(stub.props.string).toBe('a');\n      expect(stub.props.pass).toBe(obj2);\n\n      obj2.val = 'mutation';\n      rootStub.setState({ pass: obj2 });\n      renderToContainer(vNode);\n      expect(renderCallCount).toBe(5);\n      expect(stub.props.string).toBe('a');\n      expect(stub.props.passVal).toBe('otherval');\n    });\n\n    it('should throw an error if a component is not passed to the function returned by connect', () => {\n      expect(connect()).toThrow(\n        new Error(\n          'You must pass a component to the function returned by connect. Instead received undefined',\n        ),\n      );\n    });\n\n    // TODO: Refactor this test. Regex way of matching values vary per browser\n    // it('should throw an error if mapState, mapDispatch, or mergeProps returns anything but a plain object', () => {\n    //   const store = createStore(() => ({}));\n    //\n    //   const makeContainer = (mapState, mapDispatch, mergeProps) =>\n    //     createElement(\n    //       connect(mapState, mapDispatch, mergeProps)(\n    //         class Container extends Component {\n    //           render() {\n    //             return <Passthrough />;\n    //           }\n    //         }\n    //       )\n    //     );\n    //\n    //   function AwesomeMap() {}\n    //\n    //   let spyValue = '';\n    //   // mapStateToProps\n    //   const spy = spyOn(console, 'error').and.callFake(e => (spyValue = e));\n    //\n    //   renderToContainer(<ProviderMock store={store}>{makeContainer(() => 1, () => ({}), () => ({}))}</ProviderMock>);\n    //\n    //   const errorMsg = supportFnName\n    //     ? /mapStateToProps\\(\\) in Connect\\(Container\\) must return a plain object/\n    //     : /mapStateToProps\\(\\) in Connect\\(Component\\) must return a plain object/;\n    //\n    //   expect(spy.calls.count()).toBe(1);\n    //   expect(spyValue).toMatch(errorMsg);\n    //\n    //   renderToContainer(<ProviderMock store={store}>{makeContainer(() => 'hey', () => ({}), () => ({}))}</ProviderMock>);\n    //\n    //   expect(spy.calls.count()).toBe(2);\n    //   expect(spyValue).toMatch(errorMsg);\n    //\n    //   renderToContainer(<ProviderMock store={store}>{makeContainer(() => new AwesomeMap(), () => ({}), () => ({}))}</ProviderMock>);\n    //\n    //   expect(spy.calls.count()).toBe(3);\n    //   expect(spyValue).toMatch(errorMsg);\n    //\n    //   renderToContainer(<ProviderMock store={store}>{makeContainer(() => ({}), () => 1, () => ({}))}</ProviderMock>);\n    //\n    //   const errorMsg2 = supportFnName\n    //     ? /mapDispatchToProps\\(\\) in Connect\\(Container\\) must return a plain object/\n    //     : /mapDispatchToProps\\(\\) in Connect\\(Component\\) must return a plain object/;\n    //\n    //   expect(spy.calls.count()).toBe(4);\n    //   expect(spyValue).toMatch(errorMsg2);\n    //\n    //   renderToContainer(<ProviderMock store={store}>{makeContainer(() => ({}), () => 'hey', () => ({}))}</ProviderMock>);\n    //\n    //   expect(spy.calls.count()).toBe(5);\n    //   expect(spyValue).toMatch(errorMsg2);\n    //\n    //   renderToContainer(<ProviderMock store={store}>{makeContainer(() => ({}), () => new AwesomeMap(), () => ({}))}</ProviderMock>);\n    //\n    //   expect(spy.calls.count()).toBe(6);\n    //   expect(spyValue).toMatch(errorMsg2);\n    //\n    //   // mergeProps\n    //   renderToContainer(<ProviderMock store={store}>{makeContainer(() => ({}), () => ({}), () => 1)}</ProviderMock>);\n    //\n    //   const errorMsg3 = supportFnName\n    //     ? /mergeProps\\(\\) in Connect\\(Container\\) must return a plain object/\n    //     : /mergeProps\\(\\) in Connect\\(Component\\) must return a plain object/;\n    //\n    //   expect(spy.calls.count()).toBe(7);\n    //   expect(spyValue).toMatch(errorMsg3);\n    //\n    //   renderToContainer(<ProviderMock store={store}>{makeContainer(() => ({}), () => ({}), () => 'hey')}</ProviderMock>);\n    //\n    //   expect(spy.calls.count()).toBe(8);\n    //   expect(spyValue).toMatch(errorMsg3);\n    //\n    //   renderToContainer(<ProviderMock store={store}>{makeContainer(() => ({}), () => ({}), () => new AwesomeMap())}</ProviderMock>);\n    //\n    //   expect(spy.calls.count()).toBe(9);\n    //   expect(spyValue).toMatch(errorMsg3);\n    // });\n\n    it('should recalculate the state and rebind the actions on hot update', () => {\n      const store = createStore(() => {});\n\n      const ContainerBefore = connect(null, () => ({ scooby: 'doo' }))(\n        class ContainerBefore extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const ContainerAfter = connect(\n        () => ({ foo: 'baz' }),\n        () => ({ scooby: 'foo' }),\n      )(\n        class ContainerAfter extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const ContainerNext = connect(\n        () => ({ foo: 'bar' }),\n        () => ({ scooby: 'boo' }),\n      )(\n        class ContainerNext extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const tree = renderToContainer(\n        <ProviderMock store={store}>\n          <ContainerBefore />\n        </ProviderMock>,\n      );\n\n      const container = findRenderedVNodeWithType(\n        tree,\n        ContainerBefore,\n      ).children;\n      const stub = findRenderedVNodeWithType(tree, Passthrough).children;\n      expect(stub.props.foo).toBeUndefined();\n      expect(stub.props.scooby).toBe('doo');\n\n      const imitateHotReloading = (TargetClass, SourceClass) => {\n        // Crude imitation of hot reloading that does the job\n        const fns = Object.getOwnPropertyNames(SourceClass.prototype).filter(\n          (key) => typeof SourceClass.prototype[key] === 'function',\n        );\n\n        for (const key of fns) {\n          if (key !== 'render' && key !== 'constructor') {\n            TargetClass.prototype[key] = SourceClass.prototype[key];\n          }\n        }\n\n        container.forceUpdate();\n      };\n\n      imitateHotReloading(ContainerBefore, ContainerAfter);\n      expect(stub.props.foo).toBe('baz');\n      expect(stub.props.scooby).toBe('foo');\n\n      imitateHotReloading(ContainerBefore, ContainerNext);\n      expect(stub.props.foo).toBe('bar');\n      expect(stub.props.scooby).toBe('boo');\n    });\n\n    it('should set the displayName correctly', () => {\n      expect(\n        connect((state) => state)(\n          class Foo extends Component {\n            render() {\n              return <div />;\n            }\n          },\n        ).displayName,\n      ).not.toEqual(undefined);\n    });\n\n    it('should expose the wrapped component as WrappedComponent', () => {\n      class Container extends Component {\n        render() {\n          return <Passthrough />;\n        }\n      }\n\n      const decorator = connect((state) => state);\n      const decorated = decorator(Container);\n\n      expect(decorated.WrappedComponent).toBe(Container);\n    });\n\n    it('should hoist non-react statics from wrapped component', () => {\n      class Container extends Component {\n        render() {\n          return <Passthrough />;\n        }\n      }\n\n      Container.howIsRedux = () => 'Awesome!';\n      Container.foo = 'bar';\n\n      const decorator = connect((state) => state);\n      const decorated = decorator(Container);\n\n      expect(typeof decorated.howIsRedux).toBe('function');\n      expect(decorated.howIsRedux()).toBe('Awesome!');\n      expect(decorated.foo).toBe('bar');\n    });\n\n    it('should use the store from the props instead of from the context if present', () => {\n      class Container extends Component {\n        render() {\n          return <Passthrough />;\n        }\n      }\n\n      let actualState;\n\n      const expectedState = { foos: {} };\n      const decorator = connect((state) => {\n        actualState = state;\n        return {};\n      });\n\n      const Decorated = decorator(Container);\n      const mockStore = {\n        dispatch: () => {},\n        subscribe: () => {},\n        getState: () => expectedState,\n      };\n\n      renderToContainer(<Decorated store={mockStore} />);\n      expect(actualState).toBe(expectedState);\n    });\n\n    it('should throw an error if the store is not in the props or context', () => {\n      class Container extends Component {\n        render() {\n          return <Passthrough />;\n        }\n      }\n\n      const decorator = connect(() => {});\n      const Decorated = decorator(Container);\n\n      expect(() => renderToContainer(<Decorated />)).toThrow(\n        new Error(\n          'Could not find \"store\" in either the context or props of \"Connect(Container)\". Either wrap the root component in a <Provider>, or explicitly pass \"store\" as a prop to \"Connect(Container)\".',\n        ),\n      );\n    });\n\n    it('should throw when trying to access the wrapped instance if withRef is not specified', () => {\n      const store = createStore(() => ({}));\n\n      class Container extends Component {\n        render() {\n          return <Passthrough />;\n        }\n      }\n\n      const decorator = connect((state) => state);\n      const Decorated = decorator(Container);\n\n      const tree = renderToContainer(\n        <ProviderMock store={store}>\n          <Decorated />\n        </ProviderMock>,\n      );\n\n      const decorated = findRenderedVNodeWithType(tree, Decorated).children;\n      expect(() => decorated.getWrappedInstance()).toThrow(\n        new Error(\n          'To access the wrapped instance, you need to specify { withRef: true } in the options argument of the connect() call.',\n        ),\n      );\n    });\n\n    it('should return the instance of the wrapped component for use in calling child methods', () => {\n      const store = createStore(() => ({}));\n\n      const someData = {\n        some: 'data',\n      };\n\n      class Container extends Component {\n        someInstanceMethod() {\n          return someData;\n        }\n\n        render() {\n          return <Passthrough />;\n        }\n      }\n\n      const decorator = connect((state) => state, null, null, {\n        withRef: true,\n      });\n      const Decorated = decorator(Container);\n\n      const tree = renderToContainer(\n        <ProviderMock store={store}>\n          <Decorated />\n        </ProviderMock>,\n      );\n\n      const decorated = findRenderedVNodeWithType(tree, Decorated).children;\n      expect(() => decorated.someInstanceMethod()).toThrow();\n      expect(decorated.getWrappedInstance().someInstanceMethod()).toEqual(\n        someData,\n      );\n      expect(decorated.wrappedInstance.someInstanceMethod()).toBe(someData);\n    });\n\n    it('should wrap impure components without supressing updates', () => {\n      const store = createStore(() => ({}));\n\n      class ImpureComponent extends Component {\n        render() {\n          return <Passthrough statefulValue={this.context.statefulValue} />;\n        }\n      }\n\n      const decorator = connect((state) => state, null, null, { pure: false });\n      const Decorated = decorator(ImpureComponent);\n\n      class StatefulWrapper extends Component {\n        constructor() {\n          super();\n          this.state = { value: 0 };\n        }\n\n        getChildContext() {\n          return {\n            statefulValue: this.state.value,\n          };\n        }\n\n        render() {\n          return <Decorated />;\n        }\n      }\n\n      const vNode = (\n        <ProviderMock store={store}>\n          <StatefulWrapper />\n        </ProviderMock>\n      );\n      const tree = renderToContainer(vNode);\n\n      const target = findRenderedVNodeWithType(tree, Passthrough).children;\n      const wrapper = findRenderedVNodeWithType(tree, StatefulWrapper).children;\n      expect(target.props.statefulValue).toBe(0);\n\n      wrapper.setState({ value: 1 });\n      renderToContainer(vNode);\n      expect(target.props.statefulValue).toBe(1);\n    });\n\n    it('calls mapState and mapDispatch for impure components', () => {\n      const store = createStore(() => ({\n        foo: 'foo',\n        bar: 'bar',\n      }));\n\n      let mapStateToPropsCalls = 0;\n      let mapDispatchToPropsCalls = 0;\n\n      class ImpureComponent extends Component {\n        render() {\n          return <Passthrough statefulValue={this.props.value} />;\n        }\n      }\n\n      const decorator = connect(\n        (state, { storeGetter }) => {\n          mapStateToPropsCalls++;\n          return { value: state[storeGetter.storeKey] };\n        },\n        () => {\n          mapDispatchToPropsCalls++;\n          return {};\n        },\n        null,\n        { pure: false },\n      );\n      const Decorated = decorator(ImpureComponent);\n\n      class StatefulWrapper extends Component {\n        constructor() {\n          super();\n          this.state = {\n            storeGetter: { storeKey: 'foo' },\n          };\n        }\n\n        render() {\n          return <Decorated storeGetter={this.state.storeGetter} />;\n        }\n      }\n\n      const tree = renderToContainer(\n        <ProviderMock store={store}>\n          <StatefulWrapper />\n        </ProviderMock>,\n      );\n\n      const target = findRenderedVNodeWithType(tree, Passthrough).children;\n      const wrapper = findRenderedVNodeWithType(tree, StatefulWrapper).children;\n\n      expect(mapStateToPropsCalls).toBe(2);\n      expect(mapDispatchToPropsCalls).toBe(2);\n      expect(target.props.statefulValue).toBe('foo');\n\n      // Impure update\n      const storeGetter = wrapper.state.storeGetter;\n      storeGetter.storeKey = 'bar';\n      wrapper.setState({ storeGetter });\n\n      expect(mapStateToPropsCalls).toBe(3);\n      expect(mapDispatchToPropsCalls).toBe(3);\n      expect(target.props.statefulValue).toBe('bar');\n    });\n\n    it('should pass state consistently to mapState', () => {\n      const store = createStore(stringBuilder);\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      let childMapStateInvokes = 0;\n\n      const Container = connect((state) => ({ state }), null, null, {\n        withRef: true,\n      })(\n        class Container extends Component {\n          emitChange() {\n            store.dispatch({ type: 'APPEND', payload: 'b' });\n          }\n\n          render() {\n            return (\n              <div>\n                <button\n                  ref={(btn) => {\n                    this.button = btn;\n                  }}\n                  onClick={this.emitChange.bind(this)}\n                >\n                  change\n                </button>\n                <ChildContainer parentState={this.props.state} />\n              </div>\n            );\n          }\n        },\n      );\n\n      const ChildContainer = connect((state, parentProps) => {\n        childMapStateInvokes++;\n\n        // The state from parent props should always be consistent with the current state.\n        expect(state).toBe(parentProps.parentState);\n        return {};\n      })(\n        class ChildContainer extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const vNode = (\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>\n      );\n      const tree = renderToContainer(vNode);\n\n      expect(childMapStateInvokes).toBe(1);\n\n      store.dispatch({ type: 'APPEND', payload: 'c' });\n      renderToContainer(vNode);\n      expect(childMapStateInvokes).toBe(2);\n\n      const container = findRenderedVNodeWithType(tree, Container).children;\n      const button = container.getWrappedInstance().button;\n      button.click();\n      renderToContainer(vNode);\n      expect(childMapStateInvokes).toBe(3);\n\n      store.dispatch({ type: 'APPEND', payload: 'd' });\n      renderToContainer(vNode);\n      expect(childMapStateInvokes).toBe(4);\n    });\n\n    it('should not render the wrapped component when mapState does not produce change', () => {\n      const store = createStore(stringBuilder);\n      let renderCalls = 0;\n      let mapStateCalls = 0;\n\n      const Container = connect(() => {\n        mapStateCalls++;\n        return {}; // no change!\n      })(\n        class Container extends Component {\n          render() {\n            renderCalls++;\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const vNode = (\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>\n      );\n      renderToContainer(vNode);\n\n      expect(renderCalls).toBe(1);\n      expect(mapStateCalls).toBe(1);\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      renderToContainer(vNode);\n\n      // After store a change mapState has been called\n      expect(mapStateCalls).toBe(2);\n      // But render is not because it did not make any actual changes\n      expect(renderCalls).toBe(1);\n    });\n\n    it('should bail out early if mapState does not depend on props', () => {\n      const store = createStore(stringBuilder);\n      let renderCalls = 0;\n      let mapStateCalls = 0;\n      let setStateCalls = 0;\n\n      const Container = connect((state) => {\n        mapStateCalls++;\n        return state === 'aaa' ? { change: 1 } : {};\n      })(\n        class Container extends Component {\n          render() {\n            renderCalls++;\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const oldSetState = Container.prototype.setState;\n      Container.prototype.setState = function setState(...args) {\n        setStateCalls++;\n        oldSetState.apply(this, args);\n      };\n\n      const vNode = (\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>\n      );\n      renderToContainer(vNode);\n\n      expect(renderCalls).toBe(1);\n      expect(mapStateCalls).toBe(1);\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      renderToContainer(vNode);\n      expect(mapStateCalls).toBe(2);\n      expect(renderCalls).toBe(1);\n      expect(setStateCalls).toBe(0);\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      renderToContainer(vNode);\n      expect(mapStateCalls).toBe(3);\n      expect(renderCalls).toBe(1);\n      expect(setStateCalls).toBe(0);\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      renderToContainer(vNode);\n      expect(mapStateCalls).toBe(4);\n      expect(renderCalls).toBe(2);\n      expect(setStateCalls).toBe(1);\n    });\n\n    it('should not swallow errors when bailing out early', () => {\n      const store = createStore(stringBuilder);\n      let renderCalls = 0;\n      let mapStateCalls = 0;\n\n      const Container = connect((state) => {\n        mapStateCalls++;\n        if (state === 'a') {\n          throw new Error('Oops');\n        } else {\n          return {};\n        }\n      })(\n        class Container extends Component {\n          render() {\n            renderCalls++;\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      renderToContainer(\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>,\n      );\n\n      expect(renderCalls).toBe(1);\n      expect(mapStateCalls).toBe(1);\n      expect(() => store.dispatch({ type: 'APPEND', payload: 'a' })).toThrow(\n        new Error('Oops'),\n      );\n    });\n\n    it('should allow providing a factory function to mapStateToProps', () => {\n      let updateCount = 0;\n      let memoizedReturnCount = 0;\n      const store = createStore(() => ({ value: 1 }));\n\n      const mapStateFactory = () => {\n        let lastProp;\n        let lastVal;\n        let lastResult;\n        return (state, props) => {\n          if (props.name === lastProp && lastVal === state.value) {\n            memoizedReturnCount++;\n            return lastResult;\n          }\n\n          lastProp = props.name;\n          lastVal = state.value;\n          lastResult = {\n            someObject: { prop: props.name, stateVal: state.value },\n          };\n          return lastResult;\n        };\n      };\n\n      const Container = connect(mapStateFactory)(\n        class Container extends Component {\n          componentWillUpdate() {\n            updateCount++;\n          }\n\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      renderToContainer(\n        <ProviderMock store={store}>\n          <div>\n            <Container name=\"a\" />\n            <Container name=\"b\" />\n          </div>\n        </ProviderMock>,\n      );\n\n      store.dispatch({ type: 'test' });\n      expect(updateCount).toBe(0);\n      expect(memoizedReturnCount).toBe(2);\n    });\n\n    it('should allow a mapStateToProps factory consuming just state to return a function that gets ownProps', () => {\n      const store = createStore(() => ({ value: 1 }));\n\n      let initialState;\n      let initialOwnProps;\n      let secondaryOwnProps;\n      const mapStateFactory = function (factoryInitialState) {\n        initialState = factoryInitialState;\n        initialOwnProps = arguments[1];\n        return (state, props) => {\n          secondaryOwnProps = props;\n          return {};\n        };\n      };\n\n      const Container = connect(mapStateFactory)(\n        class Container extends Component {\n          render() {\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const vNode = (\n        <ProviderMock store={store}>\n          <div>\n            <Container name=\"a\" />\n          </div>\n        </ProviderMock>\n      );\n      renderToContainer(vNode);\n\n      store.dispatch({ type: 'test' });\n      renderToContainer(vNode);\n      expect(initialOwnProps).toBeUndefined();\n      expect(initialState).toBeDefined();\n      expect(secondaryOwnProps).toBeDefined();\n      expect(secondaryOwnProps.name).toBe('a');\n    });\n\n    it('should allow providing a factory function to mapDispatchToProps', (done) => {\n      let updatedCount = 0;\n      let memoizedReturnCount = 0;\n      const store = createStore(() => ({ value: 1 }));\n\n      const mapDispatchFactory = () => {\n        let lastProp;\n        let lastResult;\n        return (dispatch, props) => {\n          if (props.name === lastProp) {\n            memoizedReturnCount++;\n            return lastResult;\n          }\n\n          lastProp = props.name;\n          lastResult = { someObject: { dispatchFn: dispatch } };\n          return lastResult;\n        };\n      };\n\n      const mergeParentDispatch = (stateProps, dispatchProps, parentProps) => ({\n        ...stateProps,\n        ...dispatchProps,\n        name: parentProps.name,\n      });\n\n      const Passthrough = connect(\n        null,\n        mapDispatchFactory,\n        mergeParentDispatch,\n      )(\n        class Passthrough extends Component {\n          componentWillUpdate() {\n            updatedCount++;\n          }\n\n          render() {\n            return <div />;\n          }\n        },\n      );\n\n      class Container extends Component {\n        constructor(props) {\n          super(props);\n          this.state = { count: 0 };\n        }\n\n        componentDidMount() {\n          this.setState({ count: 1 });\n        }\n\n        render() {\n          const { count } = this.state;\n          return (\n            <div>\n              <Passthrough count={count} name=\"a\" />\n              <Passthrough count={count} name=\"b\" />\n            </div>\n          );\n        }\n      }\n      const vNode = (\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>\n      );\n      renderToContainer(vNode);\n\n      setTimeout(() => {\n        store.dispatch({ type: 'test' });\n        renderToContainer(vNode);\n        expect(updatedCount).toBe(0);\n        expect(memoizedReturnCount).toBe(2);\n        done();\n      }, 20);\n    });\n\n    it('should not call update if mergeProps return value has not changed', () => {\n      let mapStateCalls = 0;\n      let renderCalls = 0;\n      const store = createStore(stringBuilder);\n\n      const Container = connect(\n        () => ({ a: ++mapStateCalls }),\n        null,\n        () => ({\n          changed: false,\n        }),\n      )(\n        class Container extends Component {\n          render() {\n            renderCalls++;\n            return <Passthrough {...this.props} />;\n          }\n        },\n      );\n\n      const vNode = (\n        <ProviderMock store={store}>\n          <Container />\n        </ProviderMock>\n      );\n      renderToContainer(vNode);\n\n      expect(mapStateCalls).toBe(1);\n      expect(renderCalls).toBe(1);\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n      renderToContainer(vNode);\n\n      expect(mapStateCalls).toBe(2);\n      expect(renderCalls).toBe(1);\n    });\n\n    it('should update impure components with custom mergeProps', (done) => {\n      const store = createStore(() => ({}));\n      let renderCount = 0;\n\n      const Container = connect(null, null, () => ({ a: 1 }), { pure: false })(\n        class Container extends Component {\n          render() {\n            renderCount++;\n            return <div />;\n          }\n        },\n      );\n\n      class Parent extends Component {\n        componentDidMount() {\n          this.forceUpdate();\n        }\n\n        render() {\n          return <Container />;\n        }\n      }\n\n      renderToContainer(\n        <ProviderMock store={store}>\n          <Parent>\n            <Container />\n          </Parent>\n        </ProviderMock>,\n      );\n\n      expect(renderCount).toBe(1);\n\n      setTimeout(() => {\n        expect(renderCount).toBe(2);\n        done();\n      }, 20);\n    });\n\n    it('should allow to clean up child state in parent componentWillUnmount', () => {\n      const reducer = (state = { data: null }, action) => {\n        switch (action.type) {\n          case 'fetch':\n            return { data: { profile: { name: 'April' } } };\n          case 'clean':\n            return { data: null };\n          default:\n            return state;\n        }\n      };\n\n      const Child = connect((state) => ({\n        profile: state.data?.profile,\n      }))(\n        class Child extends Component {\n          render() {\n            return null;\n          }\n        },\n      );\n\n      const Parent = connect(null)(\n        class Parent extends Component {\n          componentWillMount() {\n            this.props.dispatch({ type: 'fetch' });\n          }\n\n          componentWillUnmount() {\n            this.props.dispatch({ type: 'clean' });\n          }\n\n          render() {\n            return <Child />;\n          }\n        },\n      );\n\n      const store = createStore(reducer);\n      const div = document.createElement('div');\n      render(\n        <ProviderMock store={store}>\n          <Parent />\n        </ProviderMock>,\n        div,\n      );\n\n      unmountDOM(div);\n      expect(store.getState().data).toEqual(null);\n    });\n\n    it('should allow custom displayName', () => {\n      const MyComponent = connect(null, null, null, {\n        getDisplayName: (name) => `Custom(${name})`,\n      })(\n        class MyComponent extends Component {\n          render() {\n            return <div />;\n          }\n        },\n      );\n\n      // This depends on minification, browser support, etc\n      expect(MyComponent.displayName).not.toBe(undefined);\n    });\n\n    it('should update impure components whenever the state of the store changes', () => {\n      const store = createStore(() => ({}));\n      let renderCount = 0;\n\n      const ImpureComponent = connect(() => ({}), null, null, { pure: false })(\n        class ImpureComponent extends Component {\n          render() {\n            renderCount++;\n            return <div />;\n          }\n        },\n      );\n\n      renderToContainer(\n        <ProviderMock store={store}>\n          <ImpureComponent />\n        </ProviderMock>,\n      );\n\n      const rendersBeforeStateChange = renderCount;\n      store.dispatch({ type: 'ACTION' });\n      expect(renderCount).toBe(rendersBeforeStateChange + 1);\n    });\n\n    it('should throw a helpful error for invalid mapStateToProps arguments', () => {\n      const InvalidMapState = connect('invalid')(\n        class InvalidMapState extends Component {\n          render() {\n            return <div />;\n          }\n        },\n      );\n\n      const error = renderWithBadConnect(InvalidMapState);\n      expect(error).toContain('string');\n      expect(error).toContain('mapStateToProps');\n      if (supportFnName) {\n        expect(error).toContain('InvalidMapState');\n      }\n    });\n\n    it('should throw a helpful error for invalid mapDispatchToProps arguments', () => {\n      const InvalidMapDispatch = connect(\n        null,\n        'invalid',\n      )(\n        class InvalidMapDispatch extends Component {\n          render() {\n            return <div />;\n          }\n        },\n      );\n\n      const error = renderWithBadConnect(InvalidMapDispatch);\n      expect(error).toContain('string');\n      expect(error).toContain('mapDispatchToProps');\n      if (supportFnName) {\n        expect(error).toContain('InvalidMapDispatch');\n      }\n    });\n\n    it('should throw a helpful error for invalid mergeProps arguments', () => {\n      const InvalidMerge = connect(\n        null,\n        null,\n        'invalid',\n      )(\n        class InvalidMerge extends Component {\n          render() {\n            return <div />;\n          }\n        },\n      );\n\n      const error = renderWithBadConnect(InvalidMerge);\n      expect(error).toContain('string');\n      expect(error).toContain('mergeProps');\n    });\n\n    it('should notify nested components through a blocking component', () => {\n      const store = createStore((state = 0, action) =>\n        action.type === 'INC' ? state + 1 : state,\n      );\n\n      let mapStateCalls = 0;\n      const mapStateToProps = (state) => {\n        mapStateCalls++;\n        return { count: state };\n      };\n\n      const Child = connect(mapStateToProps)(\n        class Child extends Component {\n          render() {\n            return <div>{this.props.count}</div>;\n          }\n        },\n      );\n\n      class BlockUpdates extends Component {\n        shouldComponentUpdate() {\n          return false;\n        }\n\n        render() {\n          return this.props.children;\n        }\n      }\n\n      const Parent = connect((state) => ({ count: state }))(\n        class Parent extends Component {\n          render() {\n            return (\n              <BlockUpdates>\n                <Child />\n              </BlockUpdates>\n            );\n          }\n        },\n      );\n\n      const vNode = (\n        <ProviderMock store={store}>\n          <Parent />\n        </ProviderMock>\n      );\n      renderToContainer(vNode);\n\n      expect(mapStateCalls).toBe(1);\n      store.dispatch({ type: 'INC' });\n      renderToContainer(vNode);\n      expect(mapStateCalls).toBe(2);\n    });\n\n    it('should subscribe properly when a middle connected component does not subscribe', () => {\n      const store = createStore((state = 0, action) =>\n        action.type === 'INC' ? state + 1 : state,\n      );\n\n      const C = connect((state, props) => {\n        expect(props.count).toBe(state);\n        return { count: state * 10 + props.count };\n      })(\n        class C extends Component {\n          render() {\n            return <div>{this.props.count}</div>;\n          }\n        },\n      );\n\n      // no mapStateToProps. therefore it should be transparent for subscriptions\n      const B = connect()(\n        class B extends Component {\n          render() {\n            return <C {...this.props} />;\n          }\n        },\n      );\n\n      const A = connect((state) => ({ count: state }))(\n        class A extends Component {\n          render() {\n            return <B {...this.props} />;\n          }\n        },\n      );\n\n      renderToContainer(\n        <ProviderMock store={store}>\n          <A />\n        </ProviderMock>,\n      );\n\n      store.dispatch({ type: 'INC' });\n    });\n\n    it('should subscribe properly when a new store is provided via props', () => {\n      const store1 = createStore((state = 0, action) =>\n        action.type === 'INC' ? state + 1 : state,\n      );\n      const store2 = createStore((state = 0, action) =>\n        action.type === 'INC' ? state + 1 : state,\n      );\n\n      const A = connect((state) => ({ count: state }))(\n        class A extends Component {\n          render() {\n            return <B store={store2} />;\n          }\n        },\n      );\n\n      const mapStateToPropsB = jasmine.createSpy((state) => ({ count: state }));\n      const B = connect(mapStateToPropsB)(\n        class B extends Component {\n          render() {\n            return <C {...this.props} />;\n          }\n        },\n      );\n\n      const mapStateToPropsC = jasmine.createSpy((state) => ({ count: state }));\n      const C = connect(mapStateToPropsC)(\n        class C extends Component {\n          render() {\n            return <D />;\n          }\n        },\n      );\n\n      const mapStateToPropsD = jasmine.createSpy((state) => ({ count: state }));\n      const D = connect(mapStateToPropsD)(\n        class D extends Component {\n          render() {\n            return <div>{this.props.count}</div>;\n          }\n        },\n      );\n\n      const vNode = (\n        <ProviderMock store={store1}>\n          <A />\n        </ProviderMock>\n      );\n      renderToContainer(vNode);\n\n      expect(mapStateToPropsB).toHaveBeenCalledTimes(1);\n      expect(mapStateToPropsC).toHaveBeenCalledTimes(1);\n      expect(mapStateToPropsD).toHaveBeenCalledTimes(1);\n\n      store1.dispatch({ type: 'INC' });\n      renderToContainer(vNode);\n      expect(mapStateToPropsB).toHaveBeenCalledTimes(1);\n      expect(mapStateToPropsC).toHaveBeenCalledTimes(1);\n      expect(mapStateToPropsD).toHaveBeenCalledTimes(2);\n\n      store2.dispatch({ type: 'INC' });\n      renderToContainer(vNode);\n      expect(mapStateToPropsB).toHaveBeenCalledTimes(2);\n      expect(mapStateToPropsC).toHaveBeenCalledTimes(2);\n      expect(mapStateToPropsD).toHaveBeenCalledTimes(2);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-redux/__tests__/functional.spec.jsx",
    "content": "import { render } from 'inferno';\nimport { connect } from 'inferno-redux';\nimport { createStore } from 'redux';\n\ndescribe('Inferno - redux -specifics', () => {\n  let container;\n\n  const stringBuilder = (prev = '', action) =>\n    action.type === 'APPEND' ? prev + action.payload : prev;\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    render(null, container);\n    document.body.removeChild(container);\n  });\n\n  describe('Functional component connect', () => {\n    it('Should be possible to define lifecycle events', () => {\n      const store = createStore(stringBuilder);\n      let mountedCalled = 0;\n\n      function FunctionalComponent() {\n        return <div>Hello world</div>;\n      }\n\n      const Container = connect(\n        () => ({}),\n        (dispatch) => ({\n          dispatch,\n          ref: {\n            onComponentDidMount() {\n              mountedCalled++;\n            },\n          },\n        }),\n      )(FunctionalComponent);\n\n      const div = document.createElement('div');\n\n      render(<Container store={store} />, div);\n\n      expect(mountedCalled).toBe(1);\n\n      expect(div.innerHTML).toBe('<div>Hello world</div>');\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n\n      render(<Container store={store} />, div);\n\n      expect(div.innerHTML).toBe('<div>Hello world</div>');\n      expect(mountedCalled).toBe(1);\n    });\n\n    it('Should be possible to define default lifecycle events', () => {\n      const store = createStore(stringBuilder);\n      let mountedCalled = 0;\n      let updateCounter = 0;\n\n      function FunctionalComponent(props) {\n        return <div>Hello {props.name}!</div>;\n      }\n\n      FunctionalComponent.defaultHooks = {\n        onComponentWillUpdate() {\n          updateCounter++;\n        },\n      };\n\n      const Container = connect(\n        () => ({}),\n        (dispatch) => ({\n          dispatch,\n          ref: {\n            onComponentDidMount() {\n              mountedCalled++;\n            },\n          },\n        }),\n      )(FunctionalComponent);\n\n      const div = document.createElement('div');\n\n      render(<Container name=\"Inferno\" store={store} />, div);\n\n      expect(updateCounter).toBe(0);\n      expect(mountedCalled).toBe(1);\n\n      expect(div.innerHTML).toBe('<div>Hello Inferno!</div>');\n\n      store.dispatch({ type: 'APPEND', payload: 'a' });\n\n      render(<Container name=\"Inferno1\" store={store} />, div);\n      expect(div.innerHTML).toBe('<div>Hello Inferno1!</div>');\n      expect(updateCounter).toBe(1);\n      expect(mountedCalled).toBe(1);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-redux/__tests__/utils/shallowEqual.spec.js",
    "content": "import { shallowEqual } from 'inferno-redux';\n\ndescribe('redux', () => {\n  describe('utils', () => {\n    describe('shallowEqual', () => {\n      it('should return true if arguments fields are equal', () => {\n        expect(\n          shallowEqual(\n            { a: 1, b: 2, c: undefined },\n            { a: 1, b: 2, c: undefined },\n          ),\n        ).toBe(true);\n\n        expect(shallowEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 })).toBe(\n          true,\n        );\n\n        const o = {};\n        expect(shallowEqual({ a: 1, b: 2, c: o }, { a: 1, b: 2, c: o })).toBe(\n          true,\n        );\n\n        const d = function () {\n          return 1;\n        };\n        expect(\n          shallowEqual({ a: 1, b: 2, c: o, d }, { a: 1, b: 2, c: o, d }),\n        ).toBe(true);\n      });\n\n      it('should return false if arguments fields are different function identities', () => {\n        expect(\n          shallowEqual(\n            {\n              a: 1,\n              b: 2,\n              d: function () {\n                return 1;\n              },\n            },\n            {\n              a: 1,\n              b: 2,\n              d: function () {\n                return 1;\n              },\n            },\n          ),\n        ).toBe(false);\n      });\n\n      it('should return false if first argument has too many keys', () => {\n        expect(shallowEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2 })).toBe(false);\n      });\n\n      it('should return false if second argument has too many keys', () => {\n        expect(shallowEqual({ a: 1, b: 2 }, { a: 1, b: 2, c: 3 })).toBe(false);\n      });\n\n      it('should return false if arguments have different keys', () => {\n        expect(\n          shallowEqual(\n            { a: 1, b: 2, c: undefined },\n            { a: 1, bb: 2, c: undefined },\n          ),\n        ).toBe(false);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-redux/__tests__/utils/wrapActionCreators.spec.js",
    "content": "import { wrapActionCreators } from 'inferno-redux';\n\ndescribe('Utils', () => {\n  describe('wrapActionCreators', () => {\n    it('should return a function that wraps argument in a call to bindActionCreators', () => {\n      const dispatch = (action) => ({ dispatched: action });\n      const actionResult = { an: 'action' };\n      const actionCreators = {\n        action: () => actionResult,\n      };\n\n      const wrapped = wrapActionCreators(actionCreators);\n      expect(typeof wrapped).toBe('function');\n      expect(() => wrapped(dispatch)).not.toThrow();\n      expect(() => wrapped().action()).toThrow();\n\n      const bound = wrapped(dispatch);\n      expect(bound.action).not.toThrow();\n      expect(bound.action().dispatched).toBe(actionResult);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-redux/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-redux/package.json",
    "content": "{\n  \"name\": \"inferno-redux\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Official Inferno bindings for Redux\",\n  \"author\": {\n    \"name\": \"Dominic Gannaway\",\n    \"email\": \"dg@domgan.com\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"files\": [\n    \"index.cjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"keywords\": [\n    \"babel\",\n    \"vdom\",\n    \"inferno\",\n    \"framework\",\n    \"interfaces\",\n    \"user interfaces\",\n    \"redux\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-redux\"\n  },\n  \"peerDependencies\": {\n    \"redux\": \">=4\"\n  },\n  \"dependencies\": {\n    \"inferno\": \"9.0.11\"\n  },\n  \"devDependencies\": {\n    \"inferno-create-element\": \"9.0.11\",\n    \"inferno-shared\": \"9.0.11\",\n    \"redux\": \"^4\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\"\n    ],\n    \"moduleName\": \"Inferno.Redux\",\n    \"moduleGlobals\": {\n      \"inferno\": \"Inferno\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno-redux/src/components/Provider.ts",
    "content": "import { Component, type InfernoNode } from 'inferno';\nimport { type Action, type AnyAction, type Store } from 'redux';\nimport { warning } from '../utils/warning';\n\nlet didWarnAboutReceivingStore = false;\nconst warnAboutReceivingStore = (): void => {\n  if (didWarnAboutReceivingStore) {\n    return;\n  }\n\n  didWarnAboutReceivingStore = true;\n\n  warning('<Provider> does not support changing `store` on the fly.');\n};\n\nexport interface Props<A extends Action = AnyAction> {\n  store: Store<any, A>;\n  children?: InfernoNode;\n}\n\nexport class Provider<A extends Action = AnyAction> extends Component<\n  Props<A>\n> {\n  public static displayName = 'Provider';\n  private readonly store: Store<any, A>;\n\n  constructor(props: Props<A>, context: any) {\n    super(props, context);\n    this.store = props.store;\n  }\n\n  public getChildContext(): { store: Store<any, A>; storeSubscription: null } {\n    return { store: this.store, storeSubscription: null };\n  }\n\n  // Don't infer the return type. It may be expanded and cause reference errors\n  // in the output.\n  public render(): InfernoNode {\n    return this.props.children;\n  }\n\n  public componentWillReceiveProps?(\n    nextProps: Readonly<{ children?: InfernoNode } & Props<A>>,\n    nextContext: any,\n  ): void;\n}\n\nif (process.env.NODE_ENV !== 'production') {\n  Provider.prototype.componentWillReceiveProps =\n    function componentWillReceiveProps(nextProps) {\n      const { store } = this;\n      const { store: nextStore } = nextProps;\n\n      if (store !== nextStore) {\n        warnAboutReceivingStore();\n      }\n    };\n}\n"
  },
  {
    "path": "packages/inferno-redux/src/components/connectAdvanced.ts",
    "content": "import { VNodeFlags } from 'inferno-vnode-flags';\nimport { type Dispatch, type Store } from 'redux';\nimport {\n  Component,\n  createComponentVNode,\n  type InfernoNode,\n  normalizeProps,\n} from 'inferno';\nimport { Subscription } from '../utils/Subscription';\nimport { hoistStaticProperties } from 'inferno-shared';\n\nlet hotReloadingVersion = 0;\nconst noop = (): void => {};\n\nconst makeSelectorStateful = (\n  sourceSelector: (state: any, props: any) => any,\n  store: Store<any>,\n) => {\n  // wrap the selector in an object that tracks its results between runs.\n  const selector = {\n    error: null as Error | null,\n    props: {} as any,\n    run: function runComponentSelector(props) {\n      try {\n        const nextProps = sourceSelector(store.getState(), props);\n        if (nextProps !== selector.props || selector.error) {\n          selector.shouldComponentUpdate = true;\n          selector.props = nextProps;\n          selector.error = null;\n        }\n      } catch (e) {\n        selector.shouldComponentUpdate = true;\n        selector.error = e;\n      }\n    },\n    shouldComponentUpdate: false,\n  };\n\n  return selector;\n};\n\nexport interface IConnectOptions {\n  displayName: string;\n\n  /**\n   * the func used to compute this HOC's displayName from the wrapped component's displayName.\n   * probably overridden by wrapper functions such as connect().\n   *\n   * @memberOf IConnectOptions\n   */\n  getDisplayName: (name: string) => string;\n\n  /**\n   * shown in error messages.\n   * probably overridden by wrapper functions such as connect()\n   *\n   * @type {string}\n   * @memberOf IConnectOptions\n   */\n  methodName: string;\n\n  /**\n   * if defined, the name of the property passed to the wrapped element indicating the number of\n   * calls to render. useful for watching in react devtools for unnecessary re-renders.\n   *\n   * @type {(string | null)}\n   * @memberOf IConnectOptions\n   */\n  renderCountProp: string | null;\n\n  /**\n   * determines whether this HOC subscribes to store changes.\n   *\n   * @type {boolean}\n   * @memberOf IConnectOptions\n   */\n  shouldHandleStateChanges: boolean;\n\n  /**\n   * the key of props/context to get the store.\n   *\n   * @type {string}\n   * @memberOf IConnectOptions\n   */\n  storeKey: string;\n\n  /**\n   * if true, the wrapped element is exposed by this HOC via the getWrappedInstance() function.\n   *\n   * @type {boolean}\n   * @memberOf IConnectOptions\n   */\n  withRef: boolean;\n\n  initMapStateToProps?: any;\n\n  initMapDispatchToProps?: any;\n\n  initMergeProps?: any;\n\n  pure?: any;\n\n  areStatesEqual?: any;\n\n  areOwnPropsEqual?: any;\n\n  areStatePropsEqual?: any;\n\n  areMergedPropsEqual?: any;\n\n  WrappedComponent?: any;\n\n  wrappedComponentName: string;\n}\n\n// TODO: This should be typed better. Spesifically, the output and input props should be generic.\nexport type SelectorFactory = (\n  dispatch: Dispatch<any>,\n  options: IConnectOptions,\n) => (state: any, props: any) => any;\n\n// TODO: Move\nconst invariant = (test: boolean, error: string): void => {\n  if (!test) {\n    throw new Error(error);\n  }\n};\n\nfunction getDefaultName(name): string {\n  return `ConnectAdvanced(${name})`;\n}\n\nexport function connectAdvanced(\n  selectorFactory: SelectorFactory,\n  {\n    getDisplayName = getDefaultName,\n    methodName = 'connectAdvanced',\n    renderCountProp = null,\n    shouldHandleStateChanges = true,\n    storeKey = 'store',\n    withRef = false,\n    ...connectOptions\n  }: Partial<IConnectOptions>,\n): Function {\n  const subscriptionKey = storeKey + 'Subscription';\n  const version = hotReloadingVersion++;\n\n  const wrapWithConnect = <T extends Function>(WrappedComponent: T): any => {\n    invariant(\n      typeof WrappedComponent === 'function',\n      `You must pass a component to the function returned by ` +\n        `connect. Instead received ${WrappedComponent as any}`,\n    );\n\n    const wrappedComponentName: string =\n      (WrappedComponent as any).displayName ||\n      WrappedComponent.name ||\n      'Component';\n\n    const displayName = getDisplayName(wrappedComponentName);\n\n    const selectorFactoryOptions: IConnectOptions = {\n      ...connectOptions,\n      WrappedComponent,\n      displayName,\n      getDisplayName,\n      methodName,\n      renderCountProp,\n      shouldHandleStateChanges,\n      storeKey,\n      withRef,\n      wrappedComponentName,\n    };\n\n    class Connect<P, S> extends Component<P, S> {\n      /* eslint-disable */\n      // @ts-ignore\n      public state: {};\n      /* eslint-enable */\n      public static displayName = displayName;\n      public static WrappedComponent = WrappedComponent;\n\n      public version: number;\n      private renderCount: number;\n      private readonly propsMode: boolean;\n      private store: Store<any> | null;\n      private notifyNestedSubs: (() => void) | null;\n      private subscription: Subscription | null;\n      private wrappedInstance: any;\n      private selector: {\n        error: Error | null;\n        shouldComponentUpdate: boolean;\n        props: any;\n        run: (props: any) => void;\n      };\n\n      constructor(props: P, context?: any) {\n        super(props, context);\n\n        this.version = version;\n        this.state = {};\n        this.renderCount = 0;\n        this.store = this.props[storeKey] || this.context[storeKey];\n        this.propsMode = Boolean(props[storeKey]);\n\n        this.setWrappedInstance = this.setWrappedInstance.bind(this);\n\n        invariant(\n          !!this.store,\n          `Could not find \"${storeKey}\" in either the context or ` +\n            `props of \"${displayName}\". ` +\n            `Either wrap the root component in a <Provider>, ` +\n            `or explicitly pass \"${storeKey}\" as a prop to \"${displayName}\".`,\n        );\n\n        this.initSelector();\n        this.initSubscription();\n      }\n\n      public getChildContext(): Record<string, any> {\n        // If this component received store from props, its subscription should be transparent\n        // to any descendants receiving store+subscription from context; it passes along\n        // subscription passed to it. Otherwise, it shadows the parent subscription, which allows\n        // Connect to control ordering of notifications to flow top-down.\n        const subscription = this.propsMode ? null : this.subscription;\n        return {\n          [subscriptionKey]: subscription || this.context[subscriptionKey],\n        };\n      }\n\n      public componentWillMount(): void {\n        if (!shouldHandleStateChanges || this.$SSR) {\n          return;\n        }\n\n        this.subscription!.trySubscribe();\n        this.selector.run(this.props);\n      }\n\n      public componentWillReceiveProps(nextProps): void {\n        this.selector.run(nextProps);\n      }\n\n      public shouldComponentUpdate(): boolean {\n        return this.selector.shouldComponentUpdate;\n      }\n\n      public componentWillUnmount(): void {\n        if (this.subscription) {\n          this.subscription.tryUnsubscribe();\n        }\n\n        // these are just to guard against extra memory leakage if a parent element doesn't\n        // dereference this instance properly, such as an async callback that never finishes\n        this.subscription = null;\n        this.notifyNestedSubs = noop;\n        this.store = null;\n        this.selector.run = noop;\n        this.selector.shouldComponentUpdate = false;\n      }\n\n      public getWrappedInstance() {\n        invariant(\n          withRef,\n          `To access the wrapped instance, you need to specify ` +\n            `{ withRef: true } in the options argument of the ${methodName}() call.`,\n        );\n\n        return this.wrappedInstance;\n      }\n\n      private setWrappedInstance(ref): void {\n        this.wrappedInstance = ref;\n      }\n\n      public initSelector(): void {\n        const sourceSelector = selectorFactory(\n          this.store!.dispatch,\n          selectorFactoryOptions,\n        );\n        this.selector = makeSelectorStateful(sourceSelector, this.store!);\n        this.selector.run(this.props);\n      }\n\n      public initSubscription(): void {\n        if (!shouldHandleStateChanges) {\n          return;\n        }\n\n        // parentSub's source should match where store came from: props vs. context. A component\n        // connected to the store via props shouldn't use subscription from context, or vice versa.\n        const parentSub = (this.propsMode ? this.props : this.context)[\n          subscriptionKey\n        ];\n        this.subscription = new Subscription(\n          this.store!,\n          parentSub,\n          this.onStateChange.bind(this),\n        );\n\n        // `notifyNestedSubs` is duplicated to handle the case where the component is  unmounted in\n        // the middle of the notification loop, where `this.subscription` will then be null. An\n        // extra null check every change can be avoided by copying the method onto `this` and then\n        // replacing it with a no-op on unmount. This can probably be avoided if Subscription's\n        // listeners logic is changed to not call listeners that have been unsubscribed in the\n        // middle of the notification loop.\n        this.notifyNestedSubs = this.subscription.notifyNestedSubs.bind(\n          this.subscription,\n        );\n      }\n\n      private onStateChange(): void {\n        this.selector.run(this.props);\n\n        if (!this.selector.shouldComponentUpdate) {\n          this.notifyNestedSubs!();\n        } else {\n          this.componentDidUpdate = this.notifyNestedSubsOnComponentDidUpdate;\n          this.setState({});\n        }\n      }\n\n      private notifyNestedSubsOnComponentDidUpdate(): void {\n        // `componentDidUpdate` is conditionally implemented when `onStateChange` determines it\n        // needs to notify nested subs. Once called, it unimplements itself until further state\n        // changes occur. Doing it this way vs having a permanent `componentDidMount` that does\n        // a boolean check every time avoids an extra method call most of the time, resulting\n        // in some perf boost.\n        this.componentDidUpdate = undefined;\n        this.notifyNestedSubs!();\n      }\n\n      public isSubscribed(): boolean {\n        return Boolean(this.subscription?.isSubscribed());\n      }\n\n      private addExtraProps(props: any) {\n        if (!renderCountProp) {\n          return props;\n        }\n\n        // make a shallow copy so that fields added don't leak to the original selector.\n        // this is especially important for 'ref' since that's a reference back to the component\n        // instance. a singleton memoized selector would then be holding a reference to the\n        // instance, preventing the instance from being garbage collected, and that would be bad\n        const withExtras = { ...props };\n\n        if (renderCountProp) {\n          withExtras[renderCountProp] = this.renderCount++;\n        }\n        if (this.propsMode && this.subscription) {\n          withExtras[subscriptionKey] = this.subscription;\n        }\n        return withExtras;\n      }\n\n      public render(): InfernoNode {\n        const selector = this.selector;\n        selector.shouldComponentUpdate = false;\n\n        if (selector.error) {\n          throw selector.error;\n        } else {\n          return normalizeProps(\n            createComponentVNode(\n              VNodeFlags.ComponentUnknown,\n              WrappedComponent,\n              this.addExtraProps(selector.props),\n              null,\n\n              withRef ? this.setWrappedInstance : null,\n            ),\n          );\n        }\n      }\n    }\n\n    if (process.env.NODE_ENV !== 'production') {\n      (Connect.prototype as any).componentWillUpdate =\n        function componentWillUpdate() {\n          if (this.version !== version) {\n            // We are hot reloading!\n            this.version = version;\n            this.initSelector();\n\n            if (this.subscription) {\n              this.subscription.tryUnsubscribe();\n            }\n            this.initSubscription();\n            if (shouldHandleStateChanges) {\n              this.subscription.trySubscribe();\n            }\n          }\n        };\n    }\n\n    hoistStaticProperties(Connect, WrappedComponent);\n\n    return Connect;\n  };\n\n  return wrapWithConnect;\n}\n"
  },
  {
    "path": "packages/inferno-redux/src/connect/connect.ts",
    "content": "import {\n  connectAdvanced,\n  type IConnectOptions,\n} from '../components/connectAdvanced';\nimport { type Dispatch } from 'redux';\nimport { shallowEqual } from '../utils/shallowEqual';\nimport { defaultMapDispatchToPropsFactories } from './mapDispatchToProps';\nimport { defaultMapStateToPropsFactories } from './mapStateToProps';\nimport { defaultMergePropsFactories } from './mergeProps';\nimport { defaultSelectorFactory } from './selectorFactory';\n\nconst match = (arg, factories, name): any => {\n  for (let i = factories.length - 1; i >= 0; i--) {\n    const result = factories[i](arg);\n    if (result) {\n      return result;\n    }\n  }\n\n  return (_dispatch: Dispatch<any>, options: IConnectOptions) => {\n    throw new Error(\n      `Invalid value of type ${typeof arg} for ${name} argument when connecting component ${\n        (options as any).wrappedComponentName\n      }.`,\n    );\n  };\n};\n\nconst strictEqual = (a, b): boolean => a === b;\n\n// createConnect with default args builds the 'official' connect behavior. Calling it with\n// different options opens up some testing and extensibility scenarios\nexport const createConnect =\n  ({\n    connectHOC = connectAdvanced,\n    mapStateToPropsFactories = defaultMapStateToPropsFactories,\n    mapDispatchToPropsFactories = defaultMapDispatchToPropsFactories,\n    mergePropsFactories = defaultMergePropsFactories,\n    selectorFactory = defaultSelectorFactory,\n  } = {}) =>\n  (\n    mapStateToProps?,\n    mapDispatchToProps?,\n    mergeProps?,\n    {\n      pure = true,\n      areStatesEqual = strictEqual,\n      areOwnPropsEqual = shallowEqual,\n      areStatePropsEqual = shallowEqual,\n      areMergedPropsEqual = shallowEqual,\n      ...extraOptions\n    } = {},\n  ) => {\n    const initMapStateToProps = match(\n      mapStateToProps,\n      mapStateToPropsFactories,\n      'mapStateToProps',\n    );\n    const initMapDispatchToProps = match(\n      mapDispatchToProps,\n      mapDispatchToPropsFactories,\n      'mapDispatchToProps',\n    );\n    const initMergeProps = match(mergeProps, mergePropsFactories, 'mergeProps');\n\n    return connectHOC(selectorFactory as any, {\n      // used in error messages\n      methodName: 'connect',\n\n      // used to compute Connect's displayName from the wrapped component's displayName.\n      getDisplayName: (name) => `Connect(${name})`,\n\n      // if mapStateToProps is falsy, the Connect component doesn't subscribe to store state changes\n      shouldHandleStateChanges: !!mapStateToProps,\n\n      // passed through to selectorFactory\n      areMergedPropsEqual,\n      areOwnPropsEqual,\n      areStatePropsEqual,\n      areStatesEqual,\n      initMapDispatchToProps,\n      initMapStateToProps,\n      initMergeProps,\n      pure,\n      ...extraOptions /* any extra options args can override defaults of connect or connectAdvanced */,\n    });\n  };\n\nexport const connect = createConnect();\n"
  },
  {
    "path": "packages/inferno-redux/src/connect/mapDispatchToProps.ts",
    "content": "import { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps';\n\nimport { bindActionCreators } from 'redux';\n\nexport const whenMapDispatchToPropsIsFunction = (\n  mapDispatchToProps,\n): unknown =>\n  typeof mapDispatchToProps === 'function'\n    ? wrapMapToPropsFunc(mapDispatchToProps, 'mapDispatchToProps')\n    : undefined;\n\nexport const whenMapDispatchToPropsIsMissing = (mapDispatchToProps): unknown =>\n  !mapDispatchToProps\n    ? wrapMapToPropsConstant((dispatch) => ({ dispatch }))\n    : undefined;\n\nexport const whenMapDispatchToPropsIsObject = (mapDispatchToProps): unknown =>\n  mapDispatchToProps && typeof mapDispatchToProps === 'object'\n    ? wrapMapToPropsConstant((dispatch) =>\n        bindActionCreators(mapDispatchToProps, dispatch),\n      )\n    : undefined;\n\nexport const defaultMapDispatchToPropsFactories = [\n  whenMapDispatchToPropsIsFunction,\n  whenMapDispatchToPropsIsMissing,\n  whenMapDispatchToPropsIsObject,\n];\n"
  },
  {
    "path": "packages/inferno-redux/src/connect/mapStateToProps.ts",
    "content": "import { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps';\n\nexport const whenMapStateToPropsIsFunction = (mapStateToProps): unknown =>\n  typeof mapStateToProps === 'function'\n    ? wrapMapToPropsFunc(mapStateToProps, 'mapStateToProps')\n    : undefined;\n\nexport const whenMapStateToPropsIsMissing = (mapStateToProps): unknown =>\n  !mapStateToProps ? wrapMapToPropsConstant(() => ({})) : undefined;\n\nexport const defaultMapStateToPropsFactories = [\n  whenMapStateToPropsIsFunction,\n  whenMapStateToPropsIsMissing,\n];\n"
  },
  {
    "path": "packages/inferno-redux/src/connect/mergeProps.ts",
    "content": "import { verifyPlainObject } from '../utils/verifyPlainObject';\n\nexport const defaultMergeProps = (stateProps, dispatchProps, ownProps) => ({\n  ...ownProps,\n  ...stateProps,\n  ...dispatchProps,\n});\n\nexport const wrapMergePropsFunc = (mergeProps) => {\n  return (_dispatch, { displayName, pure, areMergedPropsEqual }) => {\n    let hasRunOnce = false;\n    let mergedProps;\n\n    return function (stateProps, dispatchProps, ownProps) {\n      const nextMergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n\n      if (hasRunOnce) {\n        if (!pure || !areMergedPropsEqual(nextMergedProps, mergedProps)) {\n          mergedProps = nextMergedProps;\n        }\n      } else {\n        hasRunOnce = true;\n        mergedProps = nextMergedProps;\n\n        if (process.env.NODE_ENV !== 'production') {\n          verifyPlainObject(mergedProps, displayName, 'mergeProps');\n        }\n      }\n\n      return mergedProps;\n    };\n  };\n};\n\nexport const whenMergePropsIsFunction = (mergeProps): unknown =>\n  typeof mergeProps === 'function' ? wrapMergePropsFunc(mergeProps) : undefined;\n\nexport const whenMergePropsIsOmitted = (mergeProps): unknown =>\n  !mergeProps ? () => defaultMergeProps : undefined;\n\nexport const defaultMergePropsFactories = [\n  whenMergePropsIsFunction,\n  whenMergePropsIsOmitted,\n];\n"
  },
  {
    "path": "packages/inferno-redux/src/connect/selectorFactory.ts",
    "content": "import { verifySubselectors } from './verifySubselectors';\n\nexport const impureFinalPropsSelectorFactory = (\n  mapStateToProps,\n  mapDispatchToProps,\n  mergeProps,\n  dispatch,\n) => {\n  return (state, ownProps) => {\n    return mergeProps(\n      mapStateToProps(state, ownProps),\n      mapDispatchToProps(dispatch, ownProps),\n      ownProps,\n    );\n  };\n};\n\nexport const pureFinalPropsSelectorFactory = (\n  mapStateToProps,\n  mapDispatchToProps,\n  mergeProps,\n  dispatch,\n  { areStatesEqual, areOwnPropsEqual, areStatePropsEqual },\n) => {\n  let hasRunAtLeastOnce = false;\n  let state;\n  let ownProps;\n  let stateProps;\n  let dispatchProps;\n  let mergedProps;\n\n  const handleFirstCall = (firstState, firstOwnProps) => {\n    state = firstState;\n    ownProps = firstOwnProps;\n    stateProps = mapStateToProps(state, ownProps);\n    dispatchProps = mapDispatchToProps(dispatch, ownProps);\n    mergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n    hasRunAtLeastOnce = true;\n    return mergedProps;\n  };\n\n  const handleNewPropsAndNewState = () => {\n    stateProps = mapStateToProps(state, ownProps);\n\n    if (mapDispatchToProps.dependsOnOwnProps) {\n      dispatchProps = mapDispatchToProps(dispatch, ownProps);\n    }\n\n    mergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n    return mergedProps;\n  };\n\n  const handleNewProps = () => {\n    if (mapStateToProps.dependsOnOwnProps) {\n      stateProps = mapStateToProps(state, ownProps);\n    }\n\n    if (mapDispatchToProps.dependsOnOwnProps) {\n      dispatchProps = mapDispatchToProps(dispatch, ownProps);\n    }\n\n    mergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n    return mergedProps;\n  };\n\n  const handleNewState = () => {\n    const nextStateProps = mapStateToProps(state, ownProps);\n    const statePropsChanged = !areStatePropsEqual(nextStateProps, stateProps);\n    stateProps = nextStateProps;\n\n    if (statePropsChanged) {\n      mergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n    }\n\n    return mergedProps;\n  };\n\n  const handleSubsequentCalls = (nextState, nextOwnProps) => {\n    const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps);\n    const stateChanged = !areStatesEqual(nextState, state);\n    state = nextState;\n    ownProps = nextOwnProps;\n\n    if (propsChanged && stateChanged) {\n      return handleNewPropsAndNewState();\n    }\n    if (propsChanged) {\n      return handleNewProps();\n    }\n    if (stateChanged) {\n      return handleNewState();\n    }\n    return mergedProps;\n  };\n\n  const pureFinalPropsSelector = (nextState, nextOwnProps) =>\n    hasRunAtLeastOnce\n      ? handleSubsequentCalls(nextState, nextOwnProps)\n      : handleFirstCall(nextState, nextOwnProps);\n\n  return pureFinalPropsSelector;\n};\n\n// If pure is true, the selector returned by selectorFactory will memoize its results,\n// allowing connectAdvanced's shouldComponentUpdate to return false if final\n// props have not changed. If false, the selector will always return a new\n// object and shouldComponentUpdate will always return true.\nexport const defaultSelectorFactory = (\n  dispatch,\n  { initMapStateToProps, initMapDispatchToProps, initMergeProps, ...opts },\n) => {\n  const options: any = opts; // trick typescript\n  const mapStateToProps = initMapStateToProps(dispatch, options);\n  const mapDispatchToProps = initMapDispatchToProps(dispatch, options);\n  const mergeProps = initMergeProps(dispatch, options);\n\n  if (process.env.NODE_ENV !== 'production') {\n    verifySubselectors(\n      mapStateToProps,\n      mapDispatchToProps,\n      mergeProps,\n      options.displayName,\n    );\n  }\n\n  const selectorFactory = options.pure\n    ? pureFinalPropsSelectorFactory\n    : impureFinalPropsSelectorFactory;\n\n  return selectorFactory(\n    mapStateToProps,\n    mapDispatchToProps,\n    mergeProps,\n    dispatch,\n    options,\n  );\n};\n"
  },
  {
    "path": "packages/inferno-redux/src/connect/verifySubselectors.ts",
    "content": "import { warning } from '../utils/warning';\n\nexport const verify = (selector, methodName: string, displayName: string) => {\n  if (!selector) {\n    throw new Error(`Unexpected value for ${methodName} in ${displayName}.`);\n  }\n\n  if (methodName === 'mapStateToProps' || methodName === 'mapDispatchToProps') {\n    // eslint-disable-next-line no-prototype-builtins\n    if (!selector.hasOwnProperty('dependsOnOwnProps')) {\n      warning(\n        `The selector for ${methodName} of ${displayName} did not specify a value for dependsOnOwnProps.`,\n      );\n    }\n  }\n};\n\nexport const verifySubselectors = (\n  mapStateToProps,\n  mapDispatchToProps,\n  mergeProps,\n  displayName,\n) => {\n  verify(mapStateToProps, 'mapStateToProps', displayName);\n  verify(mapDispatchToProps, 'mapDispatchToProps', displayName);\n  verify(mergeProps, 'mergeProps', displayName);\n};\n"
  },
  {
    "path": "packages/inferno-redux/src/connect/wrapMapToProps.ts",
    "content": "import { verifyPlainObject } from '../utils/verifyPlainObject';\n\n// TODO: Type\nexport const wrapMapToPropsConstant = (getConstant) => {\n  return (dispatch, options) => {\n    const constant = getConstant(dispatch, options);\n\n    const constantSelector = (): unknown => constant;\n    (constantSelector as any).dependsOnOwnProps = false;\n    return constantSelector;\n  };\n};\n\n// dependsOnOwnProps is used by createMapToPropsProxy to determine whether to pass props as args\n// to the mapToProps function being wrapped. It is also used by makePurePropsSelector to determine\n// whether mapToProps needs to be invoked when props have changed.\n//\n// A length of one signals that mapToProps does not depend on props from the parent component.\n// A length of zero is assumed to mean mapToProps is getting args via arguments or ...args and\n// therefore not reporting its length accurately..\nexport const getDependsOnOwnProps = (mapToProps): boolean =>\n  mapToProps.dependsOnOwnProps !== null &&\n  mapToProps.dependsOnOwnProps !== undefined\n    ? !!mapToProps.dependsOnOwnProps\n    : mapToProps.length !== 1;\n\n// Used by whenMapStateToPropsIsFunction and whenMapDispatchToPropsIsFunction,\n// this function wraps mapToProps in a proxy function which does several things:\n//\n//  * Detects whether the mapToProps function being called depends on props, which\n//    is used by selectorFactory to decide if it should reinvoke on props changes.\n//\n//  * On first call, handles mapToProps if returns another function, and treats that\n//    new function as the true mapToProps for subsequent calls.\n//\n//  * On first call, verifies the first result is a plain object, in order to warn\n//    the developer that their mapToProps function is not returning a valid result.\n//\nexport const wrapMapToPropsFunc = (mapToProps, methodName) => {\n  return (_dispatch, { displayName }) => {\n    const proxy: any = (stateOrDispatch, ownProps) =>\n      proxy.dependsOnOwnProps\n        ? proxy.mapToProps(stateOrDispatch, ownProps)\n        : proxy.mapToProps(stateOrDispatch);\n\n    proxy.dependsOnOwnProps = getDependsOnOwnProps(mapToProps);\n\n    proxy.mapToProps = (stateOrDispatch, ownProps) => {\n      proxy.mapToProps = mapToProps;\n      let props = proxy(stateOrDispatch, ownProps);\n\n      if (typeof props === 'function') {\n        proxy.mapToProps = props;\n        proxy.dependsOnOwnProps = getDependsOnOwnProps(props);\n        props = proxy(stateOrDispatch, ownProps);\n      }\n\n      if (process.env.NODE_ENV !== 'production') {\n        verifyPlainObject(props, displayName, methodName);\n      }\n\n      return props;\n    };\n\n    return proxy;\n  };\n};\n"
  },
  {
    "path": "packages/inferno-redux/src/index.ts",
    "content": "import { type Dispatch } from 'redux';\nimport {\n  connectAdvanced,\n  type IConnectOptions,\n} from './components/connectAdvanced';\nimport { Provider } from './components/Provider';\nimport { connect } from './connect/connect';\nimport { wrapActionCreators } from './utils/wrapActionCreators';\nimport { shallowEqual } from './utils/shallowEqual';\n\nexport {\n  Provider,\n  connectAdvanced,\n  shallowEqual,\n  connect,\n  type IConnectOptions,\n  type Dispatch,\n  wrapActionCreators,\n};\n"
  },
  {
    "path": "packages/inferno-redux/src/utils/Subscription.ts",
    "content": "import { type Store, type Unsubscribe } from 'redux';\n\nexport type Listener = () => void;\n\ninterface IListenerCollection {\n  clear: () => void;\n  notify: () => void;\n  subscribe: (listener: Listener) => Unsubscribe;\n}\n\nconst CLEARED = null;\nconst nullSubscriptionHandler: Unsubscribe = () => {};\nconst nullListenerCollection: IListenerCollection = {\n  clear: () => {},\n  notify: () => {},\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  subscribe: (_listener: Listener) => nullSubscriptionHandler,\n};\n\nconst createListenerCollection = (): IListenerCollection => {\n  // the current/next pattern is copied from redux's createStore code.\n  let current: Listener[] | null = [];\n  let next: Listener[] | null = [];\n\n  return {\n    clear: () => {\n      next = CLEARED;\n      current = CLEARED;\n    },\n\n    notify: () => {\n      const listeners = (current = next!);\n      for (let i = 0; i < listeners.length; ++i) {\n        listeners[i]();\n      }\n    },\n\n    subscribe: (listener: Listener) => {\n      let isSubscribed = true;\n      if (next === current) {\n        next = current!.slice();\n      }\n      next!.push(listener);\n\n      return () => {\n        if (!isSubscribed || current === null) {\n          return;\n        }\n\n        isSubscribed = false;\n        if (next === current) {\n          next = current.slice();\n        }\n        next!.splice(next!.indexOf(listener), 1);\n      };\n    },\n  };\n};\n\nexport class Subscription {\n  private readonly store: Store<any>;\n  private readonly parentSub: Subscription | null;\n  private readonly onStateChange: () => void;\n  private unsubscribe: Unsubscribe | null;\n  private listeners: IListenerCollection;\n  constructor(\n    store: Store<any>,\n    parentSub: Subscription | null,\n    onStateChange: () => void,\n  ) {\n    this.store = store;\n    this.parentSub = parentSub;\n    this.onStateChange = onStateChange;\n    this.unsubscribe = null;\n    this.listeners = nullListenerCollection;\n  }\n\n  public addNestedSub(listener): Unsubscribe {\n    this.trySubscribe();\n    return this.listeners.subscribe(listener);\n  }\n\n  public notifyNestedSubs(): void {\n    this.listeners.notify();\n  }\n\n  public isSubscribed(): boolean {\n    return Boolean(this.unsubscribe);\n  }\n\n  public trySubscribe(): void {\n    if (!this.unsubscribe) {\n      this.unsubscribe = this.parentSub\n        ? this.parentSub.addNestedSub(this.onStateChange)\n        : this.store.subscribe(this.onStateChange);\n\n      this.listeners = createListenerCollection();\n    }\n  }\n\n  public tryUnsubscribe(): void {\n    if (this.unsubscribe) {\n      this.unsubscribe();\n      this.unsubscribe = null;\n      this.listeners.clear();\n      this.listeners = nullListenerCollection;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno-redux/src/utils/shallowEqual.ts",
    "content": "const hasOwn = Object.prototype.hasOwnProperty;\n\nexport const shallowEqual = (a: any, b: any): boolean => {\n  if (a === b) {\n    return true;\n  }\n\n  let countA = 0;\n  let countB = 0;\n\n  for (const key in a) {\n    if (hasOwn.call(a, key) && a[key] !== b[key]) {\n      return false;\n    }\n\n    countA++;\n  }\n\n  for (const key in b) {\n    if (hasOwn.call(b, key)) {\n      countB++;\n    }\n  }\n\n  return countA === countB;\n};\n"
  },
  {
    "path": "packages/inferno-redux/src/utils/verifyPlainObject.ts",
    "content": "import { warning } from './warning';\n\nfunction isPlainObject(value): boolean {\n  if (typeof value !== 'object' || value + '' !== '[object Object]') {\n    return false;\n  }\n  if (Object.getPrototypeOf(value) === null) {\n    return true;\n  }\n  let proto = value;\n\n  while (Object.getPrototypeOf(proto) !== null) {\n    proto = Object.getPrototypeOf(proto);\n  }\n  return Object.getPrototypeOf(value) === proto;\n}\n\nexport const verifyPlainObject = (\n  value: any,\n  displayName: string,\n  methodName: string,\n): void => {\n  if (!isPlainObject(value)) {\n    warning(\n      `${methodName}() in ${displayName} must return a plain object. Instead received ${value}.`,\n    );\n  }\n};\n"
  },
  {
    "path": "packages/inferno-redux/src/utils/warning.ts",
    "content": "export const warning = (message: string): void => {\n  if (typeof console !== 'undefined' && typeof console.error === 'function') {\n    console.error(message);\n  }\n};\n"
  },
  {
    "path": "packages/inferno-redux/src/utils/wrapActionCreators.ts",
    "content": "import { bindActionCreators, type Dispatch } from 'redux';\n\nexport function wrapActionCreators(actionCreators) {\n  return function (dispatch: Dispatch<any>) {\n    return bindActionCreators(actionCreators, dispatch);\n  };\n}\n"
  },
  {
    "path": "packages/inferno-router/README.md",
    "content": "# inferno-router\n\nInferno Router is a routing library for [Inferno](https://github.com/infernojs/inferno). It is a port of [react-router 4](https://v5.reactrouter.com/web/guides/quick-start) (later updated to v5).\n\n## Install\n\n```\nnpm install inferno-router\n```\n\n## Features\n\nSame as react-router v4 (later updated to v5), except react-native support.\n\nSee official react-router [documentation](https://v5.reactrouter.com/web/guides/philosophy)\n\nFeatures added from react-router@5:\n\n- NavLink supports passing function to className-attibute\n- NavLink supports passing function to style-attibute\n\nFeatures added from react-router@6:\n\n- Async data fetching before navigation using [`loader`-attribute](https://reactrouter.com/en/main/route/loader). See [demo](https://github.com/infernojs/inferno/tree/master/demo/inferno-router-demo).\n\nThe following features aren't supported yet:\n\n- download progress support\n- form submission\n- redirect support\n- not exposing response headers, type or status code to render method\n\n## Client side usage\n\n```js\nimport { render } from 'inferno';\nimport {\n  BrowserRouter,\n  Route,\n  Link,\n  useLoaderData,\n  useLoaderError,\n} from 'inferno-router';\n\nconst Home = () => (\n  <div>\n    <h2>Home</h2>\n  </div>\n);\n\nconst About = (props) => {\n  const data = useLoaderData(props);\n  const err = useLoaderError(props);\n\n  return (\n    <div>\n      <h2>About</h2>\n      <p>{data?.body || err?.message}</p>\n    </div>\n  );\n};\n\nconst Topic = ({ match }) => (\n  <div>\n    <h3>{match.params.topicId}</h3>\n  </div>\n);\n\nconst Topics = ({ match }) => (\n  <div>\n    <h2>Topics</h2>\n    <ul>\n      <li>\n        <Link to={`${match.url}/rendering`}>Rendering with React</Link>\n      </li>\n      <li>\n        <Link to={`${match.url}/components`}>Components</Link>\n      </li>\n      <li>\n        <Link to={`${match.url}/props-v-state`}>Props v. State</Link>\n      </li>\n    </ul>\n\n    <Route path={`${match.url}/:topicId`} component={Topic} />\n    <Route\n      exact\n      path={match.url}\n      render={() => <h3>Please select a topic.</h3>}\n    />\n  </div>\n);\n\nconst MyWebsite = () => (\n  <BrowserRouter>\n    <div>\n      <ul>\n        <li>\n          <Link to=\"/\">Home</Link>\n        </li>\n        <li>\n          <Link to=\"/about\">About</Link>\n        </li>\n        <li>\n          <Link to=\"/topics\">Topics</Link>\n        </li>\n      </ul>\n      <hr />\n      <Route exact path=\"/\" component={Home} />\n      <Route\n        path=\"/about\"\n        component={About}\n        loader={() => fetch(new URL('/api/about', BACKEND_HOST))}\n      />\n      <Route path=\"/topics\" component={Topics} />\n    </div>\n  </BrowserRouter>\n);\n\n// Render HTML on the browser\nrender(<MyWebsite />, document.getElementById('root'));\n```\n\n## Sever side usage with Koa\n\nFirst, let's create our component to render boilerplate HTML, header, body etc.\n\n```jsx\nimport Koa from 'koa';\nimport { renderToString } from 'inferno-server';\nimport { Switch, StaticRouter, Route } from 'inferno-router';\n\nconst app = new Koa();\n\nfunction Index({ children }) {\n  return (\n    <html>\n      <head>\n        <meta charSet=\"utf-8\" />\n        <title>Inferno</title>\n      </head>\n      <body>\n        <div id=\"app\">{children}</div>\n      </body>\n    </html>\n  );\n}\n\n// Example routes\nfunction Home() {\n  return <div>Welcome Home!</div>;\n}\n\nfunction Foo() {\n  return <span>Bar</span>;\n}\n\nfunction NotFound() {\n  return <h2>404</h2>;\n}\n\nconst routes = (\n  <Switch>\n    <Route exact path=\"/\" component={Home} />\n    <Route exact path=\"/demo\" component={Foo} />\n    <Route path=\"*\" component={NotFound} />\n  </Switch>\n);\n\n// Server-side render\nasync function render(ctx, next) {\n  const context = {};\n  const content = renderToString(\n    <StaticRouter location={ctx.url} context={context}>\n      <Index hostname={ctx.hostname}>{routes}</Index>\n    </StaticRouter>,\n  );\n\n  // This will contain the URL to redirect to if <Redirect> was used\n  if (context.url) {\n    return ctx.redirect(context.url);\n  }\n\n  ctx.type = 'text/html';\n  ctx.body = '<!DOCTYPE html>\\n' + content;\n  await next();\n}\n\n// Add infero render as middleware\napp.use(render);\n\napp.listen(8080, function () {\n  console.log('Listening on port ' + 8080);\n});\n```\n\n## Differences with React-Router v4\n\n- No \"official\" react-native support.\n- There's no `inferno-router-dom`, all functionality is inside `inferno-router`\n"
  },
  {
    "path": "packages/inferno-router/__tests__/BrowserRouter.spec.tsx",
    "content": "import { render } from 'inferno';\nimport { BrowserRouter } from 'inferno-router';\n\ndescribe('BrowserRouter (jsx)', () => {\n  it('puts history on context.router', () => {\n    const node = document.createElement('div');\n    let history;\n    const ContextChecker = (_props, context) => {\n      history = context.router.history;\n      return null;\n    };\n\n    render(\n      <BrowserRouter>\n        <ContextChecker />\n      </BrowserRouter>,\n      node,\n    );\n\n    expect(typeof history).toBe('object');\n  });\n\n  it('warns when passed a history prop', () => {\n    const node = document.createElement('div');\n    const history = {};\n\n    const consoleSpy = spyOn(console, 'error');\n\n    // @ts-expect-error\n    render(<BrowserRouter history={history} />, node);\n\n    expect(consoleSpy).toHaveBeenCalledTimes(1);\n\n    // browser only?\n    expect(consoleSpy.calls.argsFor(0)[0]).toContain(\n      '<BrowserRouter> ignores the history prop',\n    );\n\n    // node only?\n    // expect(console.error).toHaveBeenCalledWith(\n    //  expect.stringContaining('<BrowserRouter> ignores the history prop')\n    // )\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/HashRouter.spec.tsx",
    "content": "import { render } from 'inferno';\nimport { HashRouter } from 'inferno-router';\n\ndescribe('A <HashRouter>', () => {\n  it('puts history on context.router', () => {\n    let history;\n    const ContextChecker = (_props, context) => {\n      history = context.router.history;\n      return null;\n    };\n\n    const node = document.createElement('div');\n\n    render(\n      <HashRouter>\n        <ContextChecker />\n      </HashRouter>,\n      node,\n    );\n\n    expect(typeof history).toBe('object');\n  });\n\n  it('warns when passed a history prop', () => {\n    const history = {};\n    const node = document.createElement('div');\n\n    const consoleSpy = spyOn(console, 'error');\n\n    // @ts-expect-error\n    render(<HashRouter history={history} />, node);\n\n    expect(consoleSpy).toHaveBeenCalledTimes(1);\n    expect(consoleSpy.calls.argsFor(0)[0]).toContain(\n      '<HashRouter> ignores the history prop',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/Link.ext.spec.tsx",
    "content": "import { render } from 'inferno';\nimport { triggerEvent } from 'inferno-utils';\nimport { Link, MemoryRouter } from 'inferno-router';\n\n// These tests are not part of RR4 but it seems to be like they should pass\ndescribe('Link (jsx)', () => {\n  let node;\n  beforeEach(function () {\n    node = document.createElement('div');\n    document.body.appendChild(node);\n  });\n\n  afterEach(function () {\n    render(null, node);\n    document.body.removeChild(node);\n  });\n\n  it('should trigger when clicked', () => {\n    let history;\n    const ContextChecker = (props, context) => {\n      history = context.router.history;\n      return props.children;\n    };\n\n    render(\n      <div>\n        <MemoryRouter>\n          <ContextChecker>\n            <Link to=\"/clicked\">link</Link>\n          </ContextChecker>\n        </MemoryRouter>\n      </div>,\n      node,\n    );\n\n    const element = node.querySelector('a');\n    triggerEvent('click', element);\n    expect(history.location.pathname).toBe('/clicked');\n  });\n\n  it('should trigger custom onClick', () => {\n    const spy = jasmine.createSpy('spy');\n\n    render(\n      <MemoryRouter>\n        <Link to=\"/\" onClick={spy}>\n          link\n        </Link>\n      </MemoryRouter>,\n      node,\n    );\n    expect(spy).toHaveBeenCalledTimes(0);\n    const element = node.querySelector('a');\n    triggerEvent('click', element);\n    expect(spy).toHaveBeenCalledTimes(1);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/Link.spec.tsx",
    "content": "import {Component, InfernoNode, linkEvent, render} from 'inferno';\nimport { HashRouter, Link, MemoryRouter } from 'inferno-router';\nimport { createMemoryHistory, parsePath } from 'history';\n\ndescribe('Link (jsx)', () => {\n  let node;\n  beforeEach(function () {\n    node = document.createElement('div');\n    document.body.appendChild(node);\n  });\n\n  afterEach(function () {\n    render(null, node);\n    document.body.removeChild(node);\n  });\n\n  it('accepts a location `to` prop', () => {\n    render(\n      <MemoryRouter>\n        <Link to={parsePath('/the/path?the=query#the-hash')}>link</Link>\n      </MemoryRouter>,\n      node,\n    );\n\n    const href = node.querySelector('a').getAttribute('href');\n\n    expect(href).toEqual('/the/path?the=query#the-hash');\n  });\n\n  it('throws with no <Router>', () => {\n    expect(() => {\n      render(<Link to=\"/\">link</Link>, node);\n    }).toThrow(new Error('You should not use <Link> outside a <Router>'));\n  });\n\n  it('exposes its ref via an innerRef prop', (done) => {\n    const testNode = document.createElement('div');\n    const refCallback = (n) => {\n      expect(n.tagName).toEqual('A');\n      done();\n    };\n\n    render(\n      <MemoryRouter>\n        <Link to=\"/\" innerRef={refCallback}>\n          link\n        </Link>\n      </MemoryRouter>,\n      testNode,\n    );\n\n    expect(testNode.textContent).toEqual('link');\n  });\n});\n\ndescribe('A <Link> underneath a <HashRouter>', () => {\n  let node;\n  beforeEach(function () {\n    node = document.createElement('div');\n    document.body.appendChild(node);\n  });\n\n  afterEach(function () {\n    render(null, node);\n    document.body.removeChild(node);\n  });\n\n  const createLinkNode = (to) => {\n    render(\n      <HashRouter>\n        <Link to={to} />\n      </HashRouter>,\n      node,\n    );\n\n    return node.querySelector('a');\n  };\n\n  it('has the correct href', () => {\n    const linkNode = createLinkNode('/foo');\n    expect(linkNode.getAttribute('href')).toEqual('#/foo');\n  });\n\n  it('has the correct href #2', () => {\n    const linkNode = createLinkNode('foo');\n    expect(linkNode.getAttribute('href')).toEqual('#foo');\n  });\n\n  it('accepts a string `to` prop', () => {\n    const to = '/the/path?the=query#the-hash';\n\n    render(\n      <MemoryRouter>\n        <Link to={to}>link</Link>\n      </MemoryRouter>,\n      node,\n    );\n\n    const a = node.querySelector('a');\n\n    expect(a.getAttribute('href')).toEqual('/the/path?the=query#the-hash');\n  });\n\n  it('accepts an object `to` prop', () => {\n    const to = {\n      hash: '#the-hash',\n      pathname: '/the/path',\n      search: 'the=query',\n    };\n\n    render(\n      <MemoryRouter>\n        <Link to={to}>link</Link>\n      </MemoryRouter>,\n      node,\n    );\n\n    const a = node.querySelector('a');\n\n    expect(a.getAttribute('href')).toEqual('/the/path?the=query#the-hash');\n  });\n\n  it('accepts an object `to` prop with state', () => {\n    const memoryHistoryFoo = createMemoryHistory({\n      initialEntries: ['/foo'],\n    });\n    memoryHistoryFoo.push = jasmine.createSpy();\n\n    // clickHandler is the linkEvent handler\n    let called = false;\n    const clickHandler = linkEvent({a: 1}, (data, event) => {\n      expect(data).toBeDefined();\n      expect(data.a).toEqual(1);\n      expect(event).toBeDefined();\n      expect((event as any).type).toEqual('click');\n      called = true;\n    });\n\n    const to = {\n      hash: '#the-hash2',\n      key: '2',\n      pathname: '/the/path2',\n      search: 'the=query2',\n      state: { test: 'ok2' },\n    };\n\n    class ContextChecker extends Component<{ children?: InfernoNode }> {\n      public getChildContext() {\n        const { context } = this;\n        context.router.history = memoryHistoryFoo;\n\n        return {\n          router: context.router,\n        };\n      }\n\n      public render({ children }) {\n        return children;\n      }\n    }\n\n    render(\n      <MemoryRouter>\n        <ContextChecker>\n          <Link to={to} onClick={clickHandler}>\n            link\n          </Link>\n        </ContextChecker>\n      </MemoryRouter>,\n      node,\n    );\n\n    const a = node.querySelector('a');\n    a.click();\n\n    expect(called).toBeTruthy();\n    expect(memoryHistoryFoo.push).toHaveBeenCalledTimes(1);\n    const { hash, key, pathname, search, state } = to;\n    expect(memoryHistoryFoo.push).toHaveBeenCalledWith(\n      { hash, key, pathname, search },\n      state,\n    );\n  });\n\n  it('accepts an object `to` prop with state', () => {\n    const memoryHistoryFoo = createMemoryHistory({\n      initialEntries: ['/foo'],\n    });\n    memoryHistoryFoo.push = jasmine.createSpy();\n\n    const clickHandler = jasmine.createSpy();\n\n    const to = {\n      hash: '#the-hash',\n      key: '1',\n      pathname: '/the/path',\n      search: 'the=query',\n      state: { test: 'ok' },\n    };\n\n    class ContextChecker extends Component<{ children?: InfernoNode }> {\n      public getChildContext() {\n        const { context } = this;\n        context.router.history = memoryHistoryFoo;\n\n        return {\n          router: context.router,\n        };\n      }\n\n      public render({ children }) {\n        return children;\n      }\n    }\n\n    render(\n      <MemoryRouter>\n        <ContextChecker>\n          <Link to={to} onClick={clickHandler}>\n            link\n          </Link>\n        </ContextChecker>\n      </MemoryRouter>,\n      node,\n    );\n\n    const a = node.querySelector('a');\n    a.click();\n\n    expect(clickHandler).toHaveBeenCalledTimes(1);\n    expect(memoryHistoryFoo.push).toHaveBeenCalledTimes(1);\n    const { hash, key, pathname, search, state } = to;\n    expect(memoryHistoryFoo.push).toHaveBeenCalledWith(\n      { hash, key, pathname, search },\n      state,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/MemoryRouter.spec.tsx",
    "content": "import { render } from 'inferno';\nimport { Link, MemoryRouter, Route, Switch } from 'inferno-router';\n\ndescribe('A <MemoryRouter>', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('puts history on context.router', () => {\n    let history;\n    const ContextChecker = (_props, context) => {\n      history = context.router.history;\n      return null;\n    };\n\n    ContextChecker.contextTypes = {\n      router: () => {},\n    };\n\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter>\n        <ContextChecker />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(typeof history).toBe('object');\n  });\n\n  it('warns when passed a history prop', () => {\n    const history = {};\n    const node = document.createElement('div');\n\n    const consoleSpy = spyOn(console, 'error');\n\n    // @ts-expect-error\n    render(<MemoryRouter history={history} />, node);\n\n    expect(consoleSpy).toHaveBeenCalledTimes(1);\n    expect(consoleSpy.calls.argsFor(0)[0]).toContain(\n      '<MemoryRouter> ignores the history prop',\n    );\n  });\n\n  it('Should be possible to render multiple sub routes, Github #1360', () => {\n    function Home() {\n      return <h1>You are in home!</h1>;\n    }\n\n    function Test() {\n      return <h1>You are in test route!</h1>;\n    }\n\n    function TestOne() {\n      return <h1>You are in test-1 route!</h1>;\n    }\n\n    render(\n      <MemoryRouter>\n        <div>Header</div>\n        <Route path=\"/:lang\">\n          <Switch>\n            <Route exact path=\"/\" component={Home} />\n            <Route path=\"/test\" component={Test} />\n            <Route path=\"/test-1\" component={TestOne} />\n          </Switch>\n        </Route>\n        <ul>\n          <li>\n            <Link to=\"/test\">Home</Link>\n          </li>\n        </ul>\n        <div>Footer</div>\n      </MemoryRouter>,\n      container,\n    );\n\n    expect(container.innerHTML).toBe(\n      '<div>Header</div><h1>You are in home!</h1><ul><li><a href=\"/test\">Home</a></li></ul><div>Footer</div>',\n    );\n\n    container.querySelector('a').click();\n\n    expect(container.innerHTML).toBe(\n      '<div>Header</div><h1>You are in test route!</h1><ul><li><a href=\"/test\">Home</a></li></ul><div>Footer</div>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/NavLink.spec.tsx",
    "content": "import { createMemoryHistory } from 'history';\nimport { Component, InfernoNode, render } from 'inferno';\nimport { HashRouter, MemoryRouter, NavLink } from 'inferno-router';\n\ndescribe('NavLink', () => {\n  let node;\n\n  beforeEach(function () {\n    node = document.createElement('div');\n    document.body.appendChild(node);\n  });\n\n  afterEach(function () {\n    render(null, node);\n    document.body.removeChild(node);\n  });\n\n  describe('When a <NavLink> is active', () => {\n    it('applies its default activeClassName', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink to=\"/pizza\">Pizza!</NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).toEqual('active');\n    });\n\n    it('applies its passed activeClassName', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink to=\"/pizza\" activeClassName=\"selected\">\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n      expect(a.className).toEqual('selected');\n    });\n\n    it('applies its activeStyle', () => {\n      const defaultStyle = { color: 'black' };\n      const activeStyle = { color: 'red' };\n\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink to=\"/pizza\" style={defaultStyle} activeStyle={activeStyle}>\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.style.color).toBe(activeStyle.color);\n    });\n  });\n\n  describe('When a <NavLink> is not active', () => {\n    it('does not apply its default activeClassName', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink to=\"/salad\" activeClassName=\"selected\">\n            Salad?\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n    });\n\n    it('does not apply its passed activeClassName', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink to=\"/salad\" activeClassName=\"selected\">\n            Salad?\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n      expect(a.className).not.toContain('selected');\n    });\n\n    it('does not apply its activeStyle', () => {\n      const defaultStyle = { color: 'black' };\n      const activeStyle = { color: 'red' };\n\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink to=\"/salad\" style={defaultStyle} activeStyle={activeStyle}>\n            Salad?\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.style.color).toBe(defaultStyle.color);\n    });\n  });\n\n  describe('isActive', () => {\n    it('applies active default props when isActive returns true', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink to=\"/pizza\" isActive={() => true}>\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).toEqual('active');\n    });\n\n    it('applies active passed props when isActive returns true', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink to=\"/pizza\" activeClassName=\"selected\" isActive={() => true}>\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n      expect(a.className).toEqual('selected');\n    });\n\n    it('does not apply active default props when isActive returns false', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink to=\"/pizza\" isActive={() => false}>\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n    });\n\n    it('does not apply active passed props when isActive returns false', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink\n            to=\"/pizza\"\n            activeClassName=\"selected\"\n            isActive={() => false}\n          >\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n      expect(a.className).not.toContain('selected');\n    });\n  });\n\n  it('applies its className when provided as a function', () => {\n    render(\n      <MemoryRouter initialEntries={['/pizza']}>\n        <NavLink\n          to=\"/pizza\"\n          className={(isActive: boolean) =>\n            isActive ? 'active-pizza' : 'chill-pizza'\n          }\n        >\n          Pizza!\n        </NavLink>\n      </MemoryRouter>,\n      node,\n    );\n\n    const a = node.querySelector('a');\n    expect(a.className).toContain('active-pizza');\n  });\n\n  it('applies its style when provided as a function', () => {\n    const defaultStyle = { color: 'black' };\n    const activeStyle = { color: 'red' };\n\n    render(\n      <MemoryRouter initialEntries={['/pizza']}>\n        <NavLink\n          to=\"/pizza\"\n          style={(isActive) => (isActive ? activeStyle : defaultStyle)}\n        >\n          Pizza!\n        </NavLink>\n      </MemoryRouter>,\n      node,\n    );\n\n    const a = node.querySelector('a');\n    expect(a.style.color).toBe(activeStyle.color);\n  });\n\n  it('applies its className when provided as a function #2', () => {\n    render(\n      <MemoryRouter initialEntries={['/pizza']}>\n        <NavLink\n          to=\"/salad\"\n          className={(isActive) => (isActive ? 'active-salad' : 'chill-salad')}\n        >\n          Salad?\n        </NavLink>\n      </MemoryRouter>,\n      node,\n    );\n\n    const a = node.querySelector('a');\n    expect(a.className).toContain('chill-salad');\n  });\n\n  it('applies its style when provided as a function', () => {\n    const defaultStyle = { color: 'black' };\n    const activeStyle = { color: 'red' };\n\n    render(\n      <MemoryRouter initialEntries={['/pizza']}>\n        <NavLink\n          to=\"/salad\"\n          style={(isActive) => (isActive ? activeStyle : defaultStyle)}\n        >\n          Salad?\n        </NavLink>\n      </MemoryRouter>,\n      node,\n    );\n\n    const a = node.querySelector('a');\n    expect(a.style.color).toBe(defaultStyle.color);\n  });\n\n  describe('exact', () => {\n    it('does not do exact matching by default', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza/anchovies']}>\n          <NavLink to=\"/pizza\" activeClassName=\"active\">\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).toEqual('active');\n    });\n\n    it('sets active default value only for exact matches', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink exact to=\"/pizza\">\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).toEqual('active');\n      expect(a.getAttribute('exact')).toBeNull();\n    });\n\n    it('sets active passed value only for exact matches', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink exact to=\"/pizza\" activeClassName=\"selected\">\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n      expect(a.className).toEqual('selected');\n    });\n\n    it('does not set active default value for partial matches', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza/anchovies']}>\n          <NavLink exact to=\"/pizza\">\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n    });\n\n    it('does not set active passed value for partial matches', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza/anchovies']}>\n          <NavLink exact to=\"/pizza\" activeClassName=\"selected\">\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n      expect(a.className).not.toContain('selected');\n    });\n  });\n\n  describe(\"strict (enforce path's trailing slash)\", () => {\n    const PATH = '/pizza/';\n    it('does not do strict matching by default', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink to={PATH}>Pizza!</NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).toEqual('active');\n    });\n\n    it('does not set active default value when location.pathname has no trailing slash', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink strict to={PATH}>\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n    });\n\n    it('does not set active passed value when location.pathname has no trailing slash', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink strict to={PATH} activeClassName=\"selected\">\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n      expect(a.className).not.toContain('selected');\n    });\n\n    it('sets active default value when pathname has trailing slash', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza/']}>\n          <NavLink strict to={PATH}>\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).toEqual('active');\n    });\n\n    it('sets active passed value when pathname has trailing slash', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza/']}>\n          <NavLink strict to={PATH} activeClassName=\"selected\">\n            Pizza!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n\n      expect(a.className).not.toContain('active');\n      expect(a.className).toEqual('selected');\n    });\n  });\n\n  describe('location property', () => {\n    it('overrides the current location', () => {\n      render(\n        <MemoryRouter initialEntries={['/pizza']}>\n          <NavLink\n            to=\"/pasta\"\n            activeClassName=\"selected\"\n            location={{ pathname: '/pasta' }}\n          >\n            Pasta!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n      expect(a.className).toContain('selected');\n    });\n\n    it('is not overwritten by the current location', () => {\n      render(\n        <MemoryRouter initialEntries={['/pasta']}>\n          <NavLink\n            to=\"/pasta\"\n            activeClassName=\"selected\"\n            location={{ pathname: '/pizza' }}\n          >\n            Pasta!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.className).not.toContain('active');\n      expect(a.className).not.toContain('selected');\n      expect(node.textContent).toEqual('Pasta!');\n    });\n  });\n\n  describe('html link attributes', () => {\n    it('accept html link attributes', () => {\n      render(\n        <MemoryRouter initialEntries={['/pasta']}>\n          <NavLink to=\"/pasta\" title=\"pasta\">\n            Pasta!\n          </NavLink>\n        </MemoryRouter>,\n        node,\n      );\n      const a = node.getElementsByTagName('a')[0];\n      expect(a.title).toEqual('pasta');\n    });\n  });\n\n  describe('A <NavLink> underneath a <HashRouter>', () => {\n    let tmpNode;\n    beforeEach(function () {\n      tmpNode = document.createElement('div');\n      document.body.appendChild(tmpNode);\n    });\n\n    afterEach(function () {\n      render(null, tmpNode);\n      document.body.removeChild(tmpNode);\n    });\n\n    const createLinkNode = (to) => {\n      render(\n        <HashRouter>\n          <NavLink to={to} />\n        </HashRouter>,\n        tmpNode,\n      );\n\n      return tmpNode.querySelector('a');\n    };\n\n    it('has the correct href', () => {\n      const linkNode = createLinkNode('/foo');\n      expect(linkNode.getAttribute('href')).toEqual('#/foo');\n    });\n\n    it('has the correct href #2', () => {\n      const linkNode = createLinkNode('foo');\n      expect(linkNode.getAttribute('href')).toEqual('#foo');\n    });\n\n    it('accepts a string `to` prop', () => {\n      const to = '/the/path?the=query#the-hash';\n\n      render(\n        <MemoryRouter>\n          <NavLink to={to}>link</NavLink>\n        </MemoryRouter>,\n        tmpNode,\n      );\n\n      const a = tmpNode.querySelector('a');\n\n      expect(a.getAttribute('href')).toEqual('/the/path?the=query#the-hash');\n    });\n\n    it('accepts an object `to` prop', () => {\n      const to = {\n        hash: '#the-hash',\n        key: '1',\n        pathname: '/the/path',\n        search: 'the=query',\n        state: null,\n      };\n\n      render(\n        <MemoryRouter>\n          <NavLink to={to}>link</NavLink>\n        </MemoryRouter>,\n        tmpNode,\n      );\n\n      const a = tmpNode.querySelector('a');\n\n      expect(a.getAttribute('href')).toEqual('/the/path?the=query#the-hash');\n    });\n\n    it('accepts an object `to` prop with state', async () => {\n      const memoryHistoryFoo = createMemoryHistory({\n        initialEntries: ['/foo'],\n      });\n      memoryHistoryFoo.push = jasmine.createSpy();\n\n      const clickHandler = jasmine.createSpy();\n\n      const to = {\n        hash: '#the-hash',\n        key: '1',\n        pathname: '/the/path',\n        search: 'the=query',\n        state: { test: 'ok' },\n      };\n\n      class ContextChecker extends Component<{ children?: InfernoNode }> {\n        public getChildContext() {\n          const { context } = this;\n          context.router.history = memoryHistoryFoo;\n\n          return {\n            router: context.router,\n          };\n        }\n\n        public render({ children }) {\n          return children;\n        }\n      }\n\n      render(\n        <MemoryRouter>\n          <ContextChecker>\n            <NavLink to={to} onClick={clickHandler}>\n              link\n            </NavLink>\n          </ContextChecker>\n        </MemoryRouter>,\n        tmpNode,\n      );\n\n      const a = tmpNode.querySelector('a');\n      a.click();\n\n      expect(clickHandler).toHaveBeenCalledTimes(1);\n      expect(memoryHistoryFoo.push).toHaveBeenCalledTimes(1);\n      const { hash, key, pathname, search, state } = to;\n      expect(memoryHistoryFoo.push).toHaveBeenCalledWith(\n        { hash, key, pathname, search },\n        state,\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/Prompt.spec.tsx",
    "content": "import { Component, render } from 'inferno';\nimport { Prompt, StaticRouter } from 'inferno-router';\n\ndescribe('A <Prompt>', () => {\n  it('ask if sure to transition', () => {\n    const context = {};\n    const node = document.createElement('div');\n\n    expect(() => {\n      render(\n        <StaticRouter context={context}>\n          <Prompt when={true} message=\"this is only a test\" />\n        </StaticRouter>,\n        node,\n      );\n    }).not.toThrow();\n\n    expect(() => {\n      render(\n        <StaticRouter context={context}>\n          <Prompt when={false} message=\"this is only a test\" />\n        </StaticRouter>,\n        node,\n      );\n    }).not.toThrow();\n\n    expect(() => {\n      render(\n        <StaticRouter context={context}>\n          <Prompt when={true} message=\"this is only a test\" />\n        </StaticRouter>,\n        node,\n      );\n    }).not.toThrow();\n  });\n\n  it('blocks transition', () => {\n    const context = {};\n    const node = document.createElement('div');\n    let promptWhen;\n\n    class App extends Component {\n      private ref: any;\n      public state: any;\n\n      constructor() {\n        super();\n        this.state = { when: true };\n        promptWhen = this._setActive = this._setActive.bind(this);\n      }\n\n      private _setActive() {\n        this.setState({\n          when: false,\n        });\n      }\n\n      public componentWillUpdate(_nextProps, nextState) {\n        expect(this.ref.unblock).toBeTruthy();\n        expect(this.state.when).toBe(true);\n        expect(nextState.when).toBe(false);\n      }\n\n      public componentDidUpdate() {\n        expect(this.ref.unblock).toBeFalsy();\n      }\n\n      public render() {\n        return (\n          <Prompt\n            when={this.state.when}\n            message=\"this is only a test\"\n            ref={(c) => (this.ref = c)}\n          />\n        );\n      }\n    }\n\n    render(\n      <StaticRouter context={context}>\n        <App />\n      </StaticRouter>,\n      node,\n    );\n\n    promptWhen();\n\n    render(null, node);\n  });\n\n  it('throws when used outside Router', () => {\n    const node = document.createElement('div');\n\n    expect(() => {\n      // @ts-expect-error\n      render(<Prompt />, node);\n    }).toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/Route.spec.tsx",
    "content": "import { render } from 'inferno';\nimport { MemoryRouter, Route, Router } from 'inferno-router';\nimport { createMemoryHistory } from 'history';\n\ndescribe('A <Route>', () => {\n  it('renders at the root', () => {\n    const TEXT = 'Mrs. Kato';\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route path=\"/\" render={() => <h1>{TEXT}</h1>} />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toContain(TEXT);\n  });\n\n  it('does not render when it does not match', () => {\n    const TEXT = 'bubblegum';\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/bunnies']}>\n        <Route path=\"/flowers\" render={() => <h1>{TEXT}</h1>} />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).not.toContain(TEXT);\n  });\n\n  it('can use a `location` prop instead of `context.router.route.location`', () => {\n    const TEXT = 'tamarind chutney';\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/mint']}>\n        <Route\n          location={{ pathname: '/tamarind' }}\n          path=\"/tamarind\"\n          render={() => <h1>{TEXT}</h1>}\n        />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toContain(TEXT);\n  });\n\n  it('supports preact by nulling out children prop when empty array is passed', () => {\n    const TEXT = 'Mrs. Kato';\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route path=\"/\" render={() => <h1>{TEXT}</h1>}>\n          {[]}\n        </Route>\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toContain(TEXT);\n  });\n\n  it('matches using nextContext when updating', () => {\n    const node = document.createElement('div');\n\n    let push;\n    render(\n      <MemoryRouter initialEntries={['/sushi/california']}>\n        <Route\n          path=\"/sushi/:roll\"\n          render={({ history, match }) => {\n            push = history.push;\n            return <div>{match.url}</div>;\n          }}\n        />\n      </MemoryRouter>,\n      node,\n    );\n    push('/sushi/spicy-tuna');\n    expect(node.innerHTML).toContain('/sushi/spicy-tuna');\n  });\n\n  it('throws with no <Router>', () => {\n    const node = document.createElement('div');\n\n    expect(() => {\n      render(<Route path=\"/\" render={() => null} />, node);\n    }).toThrow(\n      new Error(\n        'You should not use <Route> or withRouter() outside a <Router>',\n      ),\n    );\n  });\n});\n\ndescribe('A <Route> with dynamic segments in the path', () => {\n  // https://github.com/remix-run/history/commit/78f016f6e5b49e2a23ec41799faf160dd68d6b6b\n  it('does not decode them', () => {\n    const node = document.createElement('div');\n    render(\n      <MemoryRouter initialEntries={['/a%20dynamic%20segment']}>\n        <Route\n          path=\"/:id\"\n          render={({ match }) => <div>{match.params.id}</div>}\n        />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toContain('a%20dynamic%20segment');\n  });\n});\n\ndescribe('A unicode <Route>', () => {\n  it('is able to match', () => {\n    const node = document.createElement('div');\n    render(\n      <MemoryRouter initialEntries={['/パス名']}>\n        <Route path=\"/パス名\" render={({ match }) => <div>{match.url}</div>} />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toContain('/パス名');\n  });\n});\n\ndescribe('<Route render>', () => {\n  const history = createMemoryHistory();\n  const node = document.createElement('div');\n\n  it('renders its return value', () => {\n    const TEXT = 'Mrs. Kato';\n    const testNode = document.createElement('div');\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route path=\"/\" render={() => <div>{TEXT}</div>} />\n      </MemoryRouter>,\n      testNode,\n    );\n\n    expect(testNode.innerHTML).toContain(TEXT);\n  });\n\n  it('receives { match, location, history } props', () => {\n    let actual: any = null;\n\n    render(\n      <Router history={history}>\n        <Route path=\"/\" render={(props) => (actual = props) && null} />\n      </Router>,\n      node,\n    );\n\n    expect(actual?.history).toBe(history);\n    expect(typeof actual?.match).toBe('object');\n    expect(typeof actual?.location).toBe('object');\n  });\n});\n\ndescribe('<Route component>', () => {\n  const history = createMemoryHistory();\n  const node = document.createElement('div');\n\n  it('renders the component', () => {\n    const TEXT = 'Mrs. Kato';\n    const testNode = document.createElement('div');\n    const Home = () => <div>{TEXT}</div>;\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route path=\"/\" component={Home} />\n      </MemoryRouter>,\n      testNode,\n    );\n\n    expect(testNode.innerHTML).toContain(TEXT);\n  });\n\n  it('receives { match, location, history } props', () => {\n    let actual: any = null;\n    const Component = (props) => (actual = props) && null;\n\n    render(\n      <Router history={history}>\n        <Route path=\"/\" component={Component} />\n      </Router>,\n      node,\n    );\n\n    expect(actual?.history).toBe(history);\n    expect(typeof actual?.match).toBe('object');\n    expect(typeof actual?.location).toBe('object');\n  });\n});\n\ndescribe('<Route children>', () => {\n  const history = createMemoryHistory();\n  const node = document.createElement('div');\n\n  it('renders a function', () => {\n    const TEXT = 'Mrs. Kato';\n    const testNode = document.createElement('div');\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route path=\"/\" children={() => <div>{TEXT}</div>} />\n      </MemoryRouter>,\n      testNode,\n    );\n\n    expect(testNode.innerHTML).toContain(TEXT);\n  });\n\n  it('renders a child element', () => {\n    const TEXT = 'Mrs. Kato';\n    const testNode = document.createElement('div');\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route path=\"/\">\n          <div>{TEXT}</div>\n        </Route>\n      </MemoryRouter>,\n      testNode,\n    );\n\n    expect(testNode.innerHTML).toContain(TEXT);\n  });\n\n  it('receives { match, location, history } props', () => {\n    let actual: any = null;\n\n    render(\n      <Router history={history}>\n        <Route path=\"/\" children={(props) => (actual = props) && null} />\n      </Router>,\n      node,\n    );\n\n    expect(actual?.history).toBe(history);\n    expect(typeof actual?.match).toBe('object');\n    expect(typeof actual?.location).toBe('object');\n  });\n});\n\ndescribe('A <Route exact>', () => {\n  it('renders when the URL does not have a trailing slash', () => {\n    const TEXT = 'bubblegum';\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/somepath/']}>\n        <Route exact path=\"/somepath\" render={() => <h1>{TEXT}</h1>} />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toContain(TEXT);\n  });\n\n  it('renders when the URL has trailing slash', () => {\n    const TEXT = 'bubblegum';\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/somepath']}>\n        <Route exact path=\"/somepath/\" render={() => <h1>{TEXT}</h1>} />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toContain(TEXT);\n  });\n});\n\ndescribe('A <Route exact strict>', () => {\n  it('does not render when the URL has a trailing slash', () => {\n    const TEXT = 'bubblegum';\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/somepath/']}>\n        <Route exact strict path=\"/somepath\" render={() => <h1>{TEXT}</h1>} />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).not.toContain(TEXT);\n  });\n\n  it('does not render when the URL does not have a trailing slash', () => {\n    const TEXT = 'bubblegum';\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/somepath']}>\n        <Route exact strict path=\"/somepath/\" render={() => <h1>{TEXT}</h1>} />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).not.toContain(TEXT);\n  });\n});\n\ndescribe('A <Route location>', () => {\n  it('can use a `location` prop instead of `router.location`', () => {\n    const TEXT = 'tamarind chutney';\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/mint']}>\n        <Route\n          location={{ pathname: '/tamarind' }}\n          path=\"/tamarind\"\n          render={() => <h1>{TEXT}</h1>}\n        />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toContain(TEXT);\n  });\n\n  describe('children', () => {\n    it(\"uses parent's prop location\", () => {\n      const TEXT = 'cheddar pretzel';\n      const node = document.createElement('div');\n\n      render(\n        <MemoryRouter initialEntries={['/popcorn']}>\n          <Route\n            location={{ pathname: '/pretzels/cheddar' }}\n            path=\"/pretzels\"\n            render={() => (\n              <Route path=\"/pretzels/cheddar\" render={() => <h1>{TEXT}</h1>} />\n            )}\n          />\n        </MemoryRouter>,\n        node,\n      );\n\n      expect(node.innerHTML).toContain(TEXT);\n    });\n\n    it(\"continues to use parent's prop location after navigation\", () => {\n      const TEXT = 'cheddar pretzel';\n      const node = document.createElement('div');\n      let push;\n      render(\n        <MemoryRouter initialEntries={['/popcorn']}>\n          <Route\n            location={{ pathname: '/pretzels/cheddar' }}\n            path=\"/pretzels\"\n            render={({ history }) => {\n              push = history.push;\n              return (\n                <Route\n                  path=\"/pretzels/cheddar\"\n                  render={() => <h1>{TEXT}</h1>}\n                />\n              );\n            }}\n          />\n        </MemoryRouter>,\n        node,\n      );\n      expect(node.innerHTML).toContain(TEXT);\n      push('/chips');\n      expect(node.innerHTML).toContain(TEXT);\n    });\n\n    it('Should throw error if element vNode is passed to component property', () => {\n      const node = document.createElement('div');\n\n      expect(() => {\n        render(\n          <MemoryRouter initialEntries={['/popcorn']}>\n            <Route component={<div>test</div>} />\n          </MemoryRouter>,\n          node,\n        );\n      }).toThrow(); // All browsers format error msg differently\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/Route.typings.spec.tsx",
    "content": "import { Component, render } from 'inferno';\nimport { Route, Router } from 'inferno-router';\nimport { createMemoryHistory } from 'history';\nimport { type IRouteProps } from '../src/Route';\n\ndescribe('<Route component>', () => {\n  const history = createMemoryHistory();\n  const node = document.createElement('div');\n\n  it('receives { history, location, match } props', () => {\n    interface RouteProps {\n      history: any;\n      location: any;\n      match: any;\n    }\n    let actual: RouteProps = {\n      history: null,\n      location: null,\n      match: null,\n    };\n    const ComponentAb = (props: RouteProps) => (actual = props) && null;\n\n    render(\n      <Router history={history}>\n        <Route path=\"/\" component={ComponentAb} />\n      </Router>,\n      node,\n    );\n\n    expect(actual.history).toBe(history);\n    expect(typeof actual.match).toBe('object');\n    expect(typeof actual.location).toBe('object');\n  });\n\n  it('type check props class component', () => {\n    class ComponentA extends Component<any, any> {\n      public render() {\n        return 'foo';\n      }\n    }\n\n    render(\n      <Router history={history}>\n        <Route path=\"/\" component={ComponentA} />\n      </Router>,\n      node,\n    );\n  });\n\n  it('type check props render method', () => {\n    class ComponentA extends Component<any, any> {\n      public render() {\n        return 'foo';\n      }\n    }\n\n    const props: IRouteProps = {\n      component: ComponentA,\n    };\n\n    const C = props.component!;\n\n    render(\n      <Router history={history}>\n        <Route path=\"/\" render={(_) => <C {...props} />} />\n      </Router>,\n      node,\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/Router.spec.tsx",
    "content": "import { render } from 'inferno';\nimport { Router } from 'inferno-router';\nimport { createMemoryHistory } from 'history';\n\ndescribe('A <Router>', () => {\n  describe('with exactly one child', () => {\n    it('does not throw an error', () => {\n      const node = document.createElement('div');\n      expect(() => {\n        render(\n          <Router history={createMemoryHistory()}>\n            <p>Bar</p>\n          </Router>,\n          node,\n        );\n      }).not.toThrow();\n    });\n  });\n\n  describe('with no children', () => {\n    it('does not throw an error', () => {\n      const node = document.createElement('div');\n      expect(() => {\n        // @ts-expect-error\n        render(<Router history={createMemoryHistory()} />, node);\n      }).not.toThrow();\n    });\n  });\n\n  describe('context', () => {\n    let rootContext;\n    const ContextChecker = (_props, context) => {\n      rootContext = context;\n      return null;\n    };\n\n    afterEach(() => {\n      rootContext = undefined;\n    });\n\n    it('puts history on context.history', () => {\n      const node = document.createElement('div');\n      const history = createMemoryHistory();\n      render(\n        <Router history={history}>\n          <ContextChecker />\n        </Router>,\n        node,\n      );\n\n      expect(rootContext.router.history).toBe(history);\n    });\n\n    it('sets context.router.route at the root', () => {\n      const node = document.createElement('div');\n      const history = createMemoryHistory({\n        initialEntries: ['/'],\n      });\n\n      render(\n        <Router history={history}>\n          <ContextChecker />\n        </Router>,\n        node,\n      );\n\n      expect(rootContext.router.route.match.path).toEqual('/');\n      expect(rootContext.router.route.match.url).toEqual('/');\n      expect(rootContext.router.route.match.params).toEqual({});\n      expect(rootContext.router.route.match.isExact).toEqual(true);\n      expect(rootContext.router.route.location).toEqual(history.location);\n    });\n\n    it('updates context.router.route upon navigation', () => {\n      const node = document.createElement('div');\n      const history = createMemoryHistory({\n        initialEntries: ['/'],\n      });\n\n      render(\n        <Router history={history}>\n          <ContextChecker />\n        </Router>,\n        node,\n      );\n\n      expect(rootContext.router.route.match.isExact).toBe(true);\n\n      const newLocation = { pathname: '/new' };\n      history.push(newLocation);\n\n      expect(rootContext.router.route.match.isExact).toBe(false);\n    });\n\n    it('does not contain context.router.staticContext by default', () => {\n      const node = document.createElement('div');\n      const history = createMemoryHistory({\n        initialEntries: ['/'],\n      });\n\n      render(\n        <Router history={history}>\n          <ContextChecker />\n        </Router>,\n        node,\n      );\n\n      expect(rootContext.router.staticContext).toBe(undefined);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/Switch.spec.tsx",
    "content": "import { render, rerender, Component } from 'inferno';\nimport { MemoryRouter, Redirect, Route, Switch } from 'inferno-router';\nimport { type IRouteProps } from '../src/Route';\n\ndescribe('Switch (jsx)', () => {\n  it('renders the first <Route> that matches the URL', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/one']}>\n        <Switch>\n          <Route path=\"/one\" render={() => <h1>one</h1>} />\n          <Route path=\"/two\" render={() => <h1>two</h1>} />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toMatch(/one/);\n  });\n\n  it('renders the first <Redirect from> that matches the URL', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/three']}>\n        <Switch>\n          <Route path=\"/one\" render={() => <h1>one</h1>} />\n          <Redirect from=\"/four\" to=\"/one\" />\n          <Redirect from=\"/three\" to=\"/two\" />\n          <Route path=\"/two\" render={() => <h1>two</h1>} />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    rerender();\n\n    expect(node.innerHTML).toMatch(/two/);\n  });\n\n  it('does not render a second <Route> or <Redirect> that also matches the URL', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/one']}>\n        <Switch>\n          <Route path=\"/one\" render={() => <h1>one</h1>} />\n          <Redirect from=\"/one\" to=\"/two\" />\n          <Route path=\"/one\" render={() => <h1>two</h1>} />\n          <Route path=\"/two\" render={() => <h1>two</h1>} />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).not.toMatch(/two/);\n  });\n\n  it('renders pathless Routes', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/cupcakes']}>\n        <Switch>\n          <Route path=\"/bubblegum\" render={() => <div>one</div>} />\n          <Route render={() => <div>two</div>} />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).not.toContain('one');\n    expect(node.innerHTML).toContain('two');\n  });\n\n  it('handles from-less Redirects', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/cupcakes']}>\n        <Switch>\n          <Route path=\"/bubblegum\" render={() => <div>bub</div>} />\n          <Redirect to=\"/bubblegum\" />\n          <Route path=\"/cupcakes\" render={() => <div>cup</div>} />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    rerender();\n\n    expect(node.innerHTML).not.toContain('cup');\n    expect(node.innerHTML).toContain('bub');\n  });\n\n  it('handles subsequent redirects', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/one']}>\n        <Switch>\n          <Redirect exact from=\"/one\" to=\"/two\" />\n          <Redirect exact from=\"/two\" to=\"/three\" />\n\n          <Route path=\"/three\" render={() => <div>three</div>} />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    rerender();\n\n    expect(node.textContent).toBe('three');\n  });\n\n  it('warns when redirecting to same route, both strings', () => {\n    const node = document.createElement('div');\n    const redirected = false;\n    let done = false;\n\n    const consoleErrSpy = spyOn(console, 'error');\n\n    render(\n      <MemoryRouter initialEntries={['/one']}>\n        <Switch>\n          <Route\n            path=\"/one\"\n            render={() => {\n              if (done) return <h1>done</h1>;\n\n              if (!redirected) {\n                return <Redirect to=\"/one\" />;\n              }\n              done = true;\n\n              return <Redirect to=\"/one\" />;\n            }}\n          />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    rerender();\n\n    expect(node.innerHTML).not.toContain('done');\n    expect(consoleErrSpy.calls.count()).toBe(1);\n    expect(consoleErrSpy.calls.argsFor(0)[0]).toContain('/one');\n  });\n\n  it('warns when redirecting to same route, mixed types', () => {\n    const node = document.createElement('div');\n    let redirected = false;\n    let done = false;\n\n    const consoleErrSpy = spyOn(console, 'error');\n\n    render(\n      <MemoryRouter initialEntries={['/one']}>\n        <Switch>\n          <Route\n            path=\"/one\"\n            render={() => {\n              if (done) return <h1>done</h1>;\n\n              if (!redirected) {\n                redirected = true;\n                return <Redirect to=\"/one\" />;\n              }\n              done = true;\n\n              return <Redirect to={{ pathname: '/one' }} />;\n            }}\n          />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    rerender();\n\n    expect(node.innerHTML).not.toContain('done');\n    expect(consoleErrSpy.calls.count()).toBe(1);\n    expect(consoleErrSpy.calls.argsFor(0)[0]).toContain('/one');\n  });\n\n  it('warns when redirecting to same route, mixed types, string with query', () => {\n    const node = document.createElement('div');\n    let redirected = false;\n    let done = false;\n\n    const consoleErrSpy = spyOn(console, 'error');\n\n    render(\n      <MemoryRouter initialEntries={['/one']}>\n        <Switch>\n          <Route\n            path=\"/one\"\n            render={() => {\n              if (done) return <h1>done</h1>;\n\n              if (!redirected) {\n                redirected = true;\n                return <Redirect to=\"/one?utm=1\" />;\n              }\n              done = true;\n\n              return <Redirect to={{ pathname: '/one', search: '?utm=1' }} />;\n            }}\n          />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    rerender();\n\n    expect(node.innerHTML).not.toContain('done');\n    expect(consoleErrSpy.calls.count()).toBe(1);\n    expect(consoleErrSpy.calls.argsFor(0)[0]).toContain('/one?utm=1');\n  });\n\n  it('does NOT warn when redirecting to same route with different `search`', () => {\n    const node = document.createElement('div');\n    let redirected = false;\n    let done = false;\n\n    const consoleErrSpy = spyOn(console, 'error');\n\n    render(\n      <MemoryRouter initialEntries={['/one']}>\n        <Switch>\n          <Route\n            path=\"/one\"\n            render={() => {\n              if (done) return <h1>done</h1>;\n\n              if (!redirected) {\n                redirected = true;\n                return <Redirect to={{ pathname: '/one', search: '?utm=1' }} />;\n              }\n              done = true;\n\n              return <Redirect to={{ pathname: '/one', search: '?utm=2' }} />;\n            }}\n          />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    rerender();\n\n    expect(node.innerHTML).toContain('done');\n    expect(consoleErrSpy.calls.count()).toBe(0);\n  });\n\n  it('handles comments', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/cupcakes']}>\n        <Switch>\n          <Route path=\"/bubblegum\" render={() => <div>bub</div>} />\n          {/* this is a comment */}\n          <Route path=\"/cupcakes\" render={() => <div>cup</div>} />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).not.toContain('bub');\n    expect(node.innerHTML).toContain('cup');\n  });\n\n  it('renders with non-element children', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/one']}>\n        <Switch>\n          <Route path=\"/one\" render={() => <h1>one</h1>} />\n          {false}\n          {undefined}\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toMatch(/one/);\n  });\n\n  it('throws with no <Router>', () => {\n    const node = document.createElement('div');\n    expect(() => {\n      render(\n        <Switch>\n          <Route path=\"/one\" render={() => <h1>one</h1>} />\n          <Route path=\"/two\" render={() => <h1>two</h1>} />\n        </Switch>,\n        node,\n      );\n    }).toThrow(new Error('You should not use <Switch> outside a <Router>'));\n  });\n\n  it('matches and renders array children correctly', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/bubblegum']}>\n        <Switch>\n          <Route path=\"/ice-cream\" render={() => <div>beb</div>} />\n          {[<Route path=\"/bubblegum\" render={() => <div>bub</div>} />]}\n          <Route path=\"/cupcakes\" render={() => <div>cup</div>} />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).not.toContain('beb');\n    expect(node.innerHTML).toContain('bub');\n    expect(node.innerHTML).not.toContain('cup');\n  });\n\n  it('matches and renders children in nested arrays correctly', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/bubblegum']}>\n        <Switch>\n          {[[<Route path=\"/ice-cream\" render={() => <div>beb</div>} />]]}\n          {[\n            <Route path=\"/something\" render={() => <div>bab</div>} />,\n            <Route path=\"/something-else\" render={() => <div>bib</div>} />,\n            [<Route path=\"/bubblegum\" render={() => <div>bub</div>} />],\n          ]}\n          <Route path=\"/cupcakes\" render={() => <div>cup</div>} />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toContain('bub');\n    expect(node.innerHTML).not.toContain('beb');\n    expect(node.innerHTML).not.toContain('bab');\n    expect(node.innerHTML).not.toContain('bib');\n    expect(node.innerHTML).not.toContain('cup');\n  });\n\n  // TODO: This will not work because component is not mandatory\n  it('Should allow using component child parameter as result, Github #1601', () => {\n    const node = document.createElement('div');\n\n    class Component1 extends Component<any, any> {\n      public state = { foo: 0 };\n      constructor(p, s) {\n        super(p, s);\n\n        this.state.foo = 1;\n      }\n\n      public render() {\n        return <div>Component</div>;\n      }\n    }\n\n    const routes: IRouteProps[] = [\n      {\n        component: Component1,\n        exact: true,\n        path: `/`,\n      },\n    ];\n\n    render(\n      <MemoryRouter initialEntries={['/bubblegum']}>\n        <Switch>\n          {routes.map(({ path, exact, component: Comp, ...rest }) => (\n            <Route\n              key={path}\n              path={path}\n              exact={exact}\n              render={(props) => <Component1 {...props} {...rest} />}\n            />\n          ))}\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n  });\n});\n\ndescribe('A <Switch location>', () => {\n  it('can use a `location` prop instead of `router.location`', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/one']}>\n        <Switch location={{ pathname: '/two' }}>\n          <Route path=\"/one\" render={() => <h1>one</h1>} />\n          <Route path=\"/two\" render={() => <h1>two</h1>} />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.innerHTML).toMatch(/two/);\n  });\n\n  describe('children', () => {\n    it('passes location prop to matched <Route>', () => {\n      const node = document.createElement('div');\n\n      let propLocation;\n      const RouteHoneytrap = (props) => {\n        propLocation = props.location;\n        return <Route {...props} />;\n      };\n\n      const switchLocation = { pathname: '/two' };\n      render(\n        <MemoryRouter initialEntries={['/one']}>\n          <Switch location={switchLocation}>\n            <Route path=\"/one\" render={() => <h1>one</h1>} />\n            <RouteHoneytrap path=\"/two\" render={() => <h1>two</h1>} />\n          </Switch>\n        </MemoryRouter>,\n        node,\n      );\n      expect(propLocation).toEqual(switchLocation);\n    });\n  });\n\n  it('renders wildcard route for unmatched paths', () => {\n    const node = document.createElement('div');\n\n    render(\n      <MemoryRouter initialEntries={['/asd']}>\n        <Switch>\n          <Route key=\"*\" path=\"*\" render={() => <h1>not found</h1>} />\n        </Switch>\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(node.textContent).toContain('not found');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/SwitchMount.spec.tsx",
    "content": "import { Component, render } from 'inferno';\nimport { Route, Router, Switch } from 'inferno-router';\nimport { createMemoryHistory } from 'history';\n\ndescribe('A <Switch>', () => {\n  it('does not remount a <Route>', () => {\n    const node = document.createElement('div');\n\n    let mountCount = 0;\n\n    class App extends Component {\n      public componentWillMount() {\n        mountCount++;\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    const history = createMemoryHistory({\n      initialEntries: ['/one'],\n    });\n\n    render(\n      <Router history={history}>\n        <Switch>\n          <Route path=\"/one\" component={App} />\n          <Route path=\"/two\" component={App} />\n        </Switch>\n      </Router>,\n      node,\n    );\n\n    expect(mountCount).toBe(1);\n\n    history.push('/two');\n\n    expect(mountCount).toBe(1);\n    history.push('/one');\n\n    expect(mountCount).toBe(1);\n  });\n\n  it('Should be possible to have multiple children in Route', () => {\n    const node = document.createElement('div');\n\n    let mountCount = 0;\n\n    class App extends Component {\n      public componentWillMount() {\n        mountCount++;\n      }\n\n      public render() {\n        return <div />;\n      }\n    }\n\n    function Foobar() {\n      return <span>Okay</span>;\n    }\n\n    const history = createMemoryHistory({\n      initialEntries: ['/one'],\n    });\n\n    render(\n      <Router history={history}>\n        <Switch>\n          <Route path=\"/one\">\n            <App />\n            <App />\n            <div>Test</div>\n          </Route>\n          <Route path=\"/two\">\n            <Foobar />\n          </Route>\n        </Switch>\n      </Router>,\n      node,\n    );\n\n    expect(node.innerHTML).toBe('<div></div><div></div><div>Test</div>');\n\n    history.push('/two');\n\n    expect(node.innerHTML).toBe('<span>Okay</span>');\n\n    history.push('/one');\n\n    expect(node.innerHTML).toBe('<div></div><div></div><div>Test</div>');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/github1176.spec.tsx",
    "content": "import { Component, render } from 'inferno';\nimport { Link, Route, Router, Switch } from 'inferno-router';\nimport { triggerEvent } from 'inferno-utils';\nimport { createMemoryHistory } from 'history';\n\ndescribe('Github1176', () => {\n  let container;\n  const browserHistory = createMemoryHistory();\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should not crash', (done) => {\n    const Loader = () => <div className=\"loader\">Loader...</div>;\n\n    class Component1 extends Component<any, any> {\n      public render() {\n        return (\n          <div className=\"component1\">\n            Component 1 <br />\n            <Link id=\"com2\" to=\"/component2\">\n              Link to component 2\n            </Link>\n          </div>\n        );\n      }\n    }\n\n    class Component2 extends Component<any, any> {\n      constructor(props) {\n        super(props);\n\n        this.state = {\n          loading: true,\n        };\n      }\n\n      public componentDidMount() {\n        setTimeout(() => {\n          this.setState({\n            loading: false,\n          });\n        }, 10);\n      }\n\n      public clearApp() {\n        render(null, container);\n      }\n\n      public render() {\n        if ((this.state as any).loading) {\n          return <Loader />;\n        }\n\n        return (\n          <div className=\"component2\">\n            Component 2 <br />\n            <span id=\"clear\" onClick={this.clearApp}>\n              clear app\n            </span>\n          </div>\n        );\n      }\n    }\n\n    function Foobar() {\n      return <div>Ok</div>;\n    }\n\n    const routes = (\n      <Router history={browserHistory}>\n        <Switch>\n          <Route component={Component1} path=\"/\" exact />\n          <Route component={Component2} path=\"/component2\" exact />\n          <Route component={Foobar} path=\"/component333\" exact />\n        </Switch>\n      </Router>\n    );\n\n    render(routes, container);\n\n    expect(container.querySelectorAll('.component1').length).toBe(1);\n    const div2 = container.querySelector('#com2');\n    triggerEvent('click', div2);\n\n    setTimeout(() => {\n      expect(container.querySelectorAll('.component1').length).toBe(0);\n      expect(container.querySelectorAll('.component2').length).toBe(1);\n\n      const clear = container.querySelector('#clear');\n      clear.click();\n\n      expect(container.innerHTML).toBe('');\n      expect(container.querySelectorAll('.component2').length).toBe(0);\n      expect(container.querySelectorAll('.component1').length).toBe(0);\n      done();\n    }, 25);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/integration.spec.tsx",
    "content": "import { render } from 'inferno';\nimport { MemoryRouter, Route } from 'inferno-router';\n\ndescribe('Integration Tests', () => {\n  it('renders nested matches', () => {\n    const node = document.createElement('div');\n    const TEXT1 = 'Ms. Tripp';\n    const TEXT2 = 'Mrs. Schiffman';\n    render(\n      <MemoryRouter initialEntries={['/nested']}>\n        <Route\n          path=\"/\"\n          render={() => (\n            <div>\n              <h1>{TEXT1}</h1>\n              <Route path=\"/nested\" render={() => <h2>{TEXT2}</h2>} />\n            </div>\n          )}\n        />\n      </MemoryRouter>,\n      node,\n    );\n    expect(node.innerHTML).toContain(TEXT1);\n    expect(node.innerHTML).toContain(TEXT2);\n  });\n\n  it('renders only as deep as the matching Route', () => {\n    const node = document.createElement('div');\n    const TEXT1 = 'Ms. Tripp';\n    const TEXT2 = 'Mrs. Schiffman';\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route\n          path=\"/\"\n          render={() => (\n            <div>\n              <h1>{TEXT1}</h1>\n              <Route path=\"/nested\" render={() => <h2>{TEXT2}</h2>} />\n            </div>\n          )}\n        />\n      </MemoryRouter>,\n      node,\n    );\n    expect(node.innerHTML).toContain(TEXT1);\n    expect(node.innerHTML).not.toContain(TEXT2);\n  });\n\n  it('renders multiple matching routes', () => {\n    const node = document.createElement('div');\n    const TEXT1 = 'Mrs. Schiffman';\n    const TEXT2 = 'Mrs. Burton';\n    render(\n      <MemoryRouter initialEntries={['/double']}>\n        <div>\n          <aside>\n            <Route path=\"/double\" render={() => <h1>{TEXT1}</h1>} />\n          </aside>\n          <main>\n            <Route path=\"/double\" render={() => <h1>{TEXT2}</h1>} />\n          </main>\n        </div>\n      </MemoryRouter>,\n      node,\n    );\n    expect(node.innerHTML).toContain(TEXT1);\n    expect(node.innerHTML).toContain(TEXT2);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/issue1322.spec.tsx",
    "content": "import { render } from 'inferno';\nimport { Link, MemoryRouter, NavLink, Route } from 'inferno-router';\n\ndescribe('Github #1322', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should _always_ patch children when route is changed', () => {\n    const Home = () => (\n      <div>\n        <h2>Home</h2>\n      </div>\n    );\n\n    const About = () => (\n      <div>\n        <h2>About</h2>\n      </div>\n    );\n\n    const Topic = ({ match }) => (\n      <div>\n        <h3>{match.params.topicId}</h3>\n      </div>\n    );\n\n    const Topics = ({ match }) => (\n      <div>\n        <h2>Topics</h2>\n        <ul>\n          <li>\n            <Link to={`${match.url}/rendering`}>Rendering with React</Link>\n          </li>\n          <li>\n            <Link to={`${match.url}/components`}>Components</Link>\n          </li>\n          <li>\n            <Link to={`${match.url}/props-v-state`}>Props v. State</Link>\n          </li>\n        </ul>\n\n        <Route path={`${match.url}/:topicId`} component={Topic} />\n        <Route\n          exact\n          path={match.url}\n          render={() => <h3>Please select a topic.</h3>}\n        />\n      </div>\n    );\n\n    const MyWebsite = () => (\n      <MemoryRouter>\n        <div>\n          <ul>\n            <li>\n              <Link to=\"/\">Home</Link>\n            </li>\n            <li>\n              <Link to=\"/about\">About</Link>\n            </li>\n            <li>\n              <Link to=\"/topics\">Topics</Link>\n            </li>\n          </ul>\n\n          <hr />\n\n          <Route exact path=\"/\" component={Home} />\n          <Route path=\"/about\" component={About} />\n          <Route path=\"/topics\" component={Topics} />\n        </div>\n      </MemoryRouter>\n    );\n\n    render(<MyWebsite />, container);\n\n    expect(container.querySelector('h2').innerHTML).toEqual('Home');\n\n    const aboutLink = container.querySelectorAll('a')[1];\n\n    aboutLink.click();\n\n    expect(container.querySelector('h2').innerHTML).toEqual('About');\n\n    const homeLink = container.querySelectorAll('a')[0];\n\n    homeLink.click();\n\n    expect(container.querySelector('h2').innerHTML).toEqual('Home');\n  });\n\n  it('Should change activeClass on links without functional component Wrapper, Github #1345', () => {\n    function CompList() {\n      return <div id=\"first\">FIRST</div>;\n    }\n\n    function CreateComp() {\n      return <div id=\"second\">SECOND</div>;\n    }\n\n    const tree = (\n      <MemoryRouter>\n        <div>\n          <nav class=\"navbar navbar-expand-lg navbar-light bg-light\">\n            <div\n              class=\"container py-2\"\n              style=\"border-bottom: 1px solid rgba(0, 0, 0, 0.13);\"\n            >\n              <div class=\"collapse navbar-collapse\" id=\"navbarNav\">\n                <ul class=\"navbar-nav text-muted\">\n                  <li class=\"nav-item mr-2\">\n                    <NavLink exact to=\"/\" activeClassName=\"active\">\n                      Play\n                    </NavLink>\n                  </li>\n                  <li class=\"nav-item mr-2\">\n                    <NavLink to=\"/create\" activeClassName=\"active\">\n                      Create\n                    </NavLink>\n                  </li>\n                  <li class=\"nav-item mr-2\">\n                    <NavLink to=\"/publish\" activeClassName=\"active\">\n                      Publish\n                    </NavLink>\n                  </li>\n                </ul>\n              </div>\n            </div>\n          </nav>\n          <Route exact path=\"/\" component={CompList} />\n          <Route path=\"/create\" component={CreateComp} />\n          <Route path=\"/publish\" component={() => <div>Publish</div>} />\n        </div>\n      </MemoryRouter>\n    );\n\n    render(tree, container);\n\n    expect(container.querySelector('#first')).toBeDefined();\n\n    const links = container.querySelectorAll('li');\n\n    expect(links[0].firstChild.classList.contains('active')).toBeTruthy();\n\n    links[1].firstChild.click();\n\n    expect(links[0].firstChild.classList.contains('active')).toBeFalsy();\n    expect(links[1].firstChild.classList.contains('active')).toBeTruthy();\n    expect(container.querySelector('#first')).toBeNull();\n    expect(container.querySelector('#second')).toBeDefined();\n\n    links[0].firstChild.click();\n    expect(links[0].firstChild.classList.contains('active')).toBeTruthy();\n    expect(links[1].firstChild.classList.contains('active')).toBeFalsy();\n    expect(container.querySelector('#first')).toBeDefined();\n    expect(container.querySelector('#second')).toBeNull();\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/loaderOnRoute.spec.tsx",
    "content": "import { render } from 'inferno';\nimport {\n  BrowserRouter,\n  MemoryRouter,\n  StaticRouter,\n  Route,\n  NavLink,\n  useLoaderData,\n  useLoaderError,\n  resolveLoaders,\n  traverseLoaders,\n} from 'inferno-router';\n// Cherry picked relative import so we don't get node-stuff from inferno-server in browser test\nimport { createEventGuard, createResponse } from './testUtils';\n\ndescribe('A <Route> with loader in a MemoryRouter', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('renders on initial', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEXT = 'ok';\n    const loaderFunc = async () => {\n      setDone();\n      return { message: TEXT };\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route\n          path=\"/\"\n          render={(props: any) => {\n            const data = useLoaderData(props);\n            return <h1>{data?.message}</h1>;\n          }}\n          loader={loaderFunc}\n        />\n      </MemoryRouter>,\n      container,\n    );\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('renders error on initial', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEXT = 'An error';\n    const loaderFunc = async () => {\n      setDone();\n      throw new Error(TEXT);\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route\n          path=\"/\"\n          render={(props: any) => {\n            const err = useLoaderError(props);\n            return <h1>{err?.message}</h1>;\n          }}\n          loader={loaderFunc}\n        />\n      </MemoryRouter>,\n      container,\n    );\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('Can access initialData (for hydration)', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n    const initialData = {\n      '/flowers': { res: await loaderFunc(), err: undefined },\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/flowers']} initialData={initialData}>\n        <Route path=\"/flowers\" render={Component} loader={loaderFunc} />\n      </MemoryRouter>,\n      container,\n    );\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('Should render component after after click', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEST = 'ok';\n    const loaderFunc = async () => {\n      setDone();\n      return { message: TEST };\n    };\n\n    function RootComp() {\n      return <div id=\"root\">ROOT</div>;\n    }\n\n    function CreateComp(props) {\n      const res = useLoaderData(props);\n      return <div id=\"create\">{res.message}</div>;\n    }\n\n    function PublishComp() {\n      return <div id=\"publish\">PUBLISH</div>;\n    }\n\n    const tree = (\n      <MemoryRouter>\n        <div>\n          <nav>\n            <ul>\n              <li>\n                <NavLink exact to=\"/\">\n                  Play\n                </NavLink>\n              </li>\n              <li id=\"createNav\">\n                <NavLink to=\"/create\">Create</NavLink>\n              </li>\n              <li>\n                <NavLink to=\"/publish\">Publish</NavLink>\n              </li>\n            </ul>\n          </nav>\n          <Route exact path=\"/\" component={RootComp} />\n          <Route path=\"/create\" component={CreateComp} loader={loaderFunc} />\n          <Route path=\"/publish\" component={PublishComp} />\n        </div>\n      </MemoryRouter>\n    );\n\n    render(tree, container);\n\n    expect(container.innerHTML).toContain('ROOT');\n\n    // Click create\n    const link = container.querySelector('#createNav');\n    link.firstChild.click();\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.querySelector('#create').innerHTML).toContain(TEST);\n  });\n\n  it('Should recieve params in loader', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return (\n        <div>\n          <h1>{res?.message}</h1>\n          <p>{res?.slug}</p>\n        </div>\n      );\n    };\n    const loaderFunc = async ({ params: paramsIn }: any) => {\n      return { message: TEXT, slug: paramsIn?.slug };\n    };\n\n    const params = { slug: 'flowers' };\n    const initialData = {\n      '/:slug': { res: await loaderFunc({ params }), err: undefined },\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/flowers']} initialData={initialData}>\n        <Route path=\"/:slug\" render={Component} loader={loaderFunc} />\n      </MemoryRouter>,\n      container,\n    );\n\n    expect(container.innerHTML).toContain(TEXT);\n    expect(container.innerHTML).toContain('flowers');\n  });\n\n  it('Can abort fetch', async () => {\n    const abortCalls = {\n      nrofCalls: 0,\n    };\n    const _abortFn = AbortController.prototype.abort;\n    AbortController.prototype.abort = () => {\n      abortCalls.nrofCalls++;\n    };\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEST = 'ok';\n\n    const loaderFunc = async ({ request }) => {\n      expect(request).toBeDefined();\n      expect(request.signal).toBeDefined();\n      return await new Promise((resolve) => {\n        setTimeout(() => {\n          setDone();\n          resolve({ message: TEST });\n        }, 5);\n      });\n    };\n\n    function RootComp() {\n      return <div id=\"root\">ROOT</div>;\n    }\n\n    function CreateComp(props) {\n      const res = useLoaderData(props);\n      return <div id=\"create\">{res.message}</div>;\n    }\n\n    function PublishComp() {\n      return <div id=\"publish\">PUBLISH</div>;\n    }\n\n    const tree = (\n      <MemoryRouter>\n        <div>\n          <nav>\n            <ul>\n              <li>\n                <NavLink exact to=\"/\">\n                  Play\n                </NavLink>\n              </li>\n              <li id=\"createNav\">\n                <NavLink to=\"/create\">Create</NavLink>\n              </li>\n              <li id=\"publishNav\">\n                <NavLink to=\"/publish\">Publish</NavLink>\n              </li>\n            </ul>\n          </nav>\n          <Route exact path=\"/\" component={RootComp} />\n          <Route path=\"/create\" component={CreateComp} loader={loaderFunc} />\n          <Route path=\"/publish\" component={PublishComp} />\n        </div>\n      </MemoryRouter>\n    );\n\n    render(tree, container);\n\n    expect(container.innerHTML).toContain('ROOT');\n\n    // Click create\n    container.querySelector('#createNav').firstChild.click();\n    container.querySelector('#publishNav').firstChild.click();\n\n    await waitForRerender();\n\n    expect(abortCalls.nrofCalls).toEqual(1);\n    expect(container.querySelector('#create')).toBeNull();\n    AbortController.prototype.abort = _abortFn;\n  });\n});\n\ndescribe('A <Route> with loader in a BrowserRouter', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n    // Reset history to root\n    history.replaceState(undefined, '', '/');\n  });\n\n  it('renders on initial', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEXT = 'ok';\n    const loaderFunc = async () => {\n      setDone();\n      return { message: TEXT };\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route\n          path=\"/\"\n          render={(props: any) => {\n            const data = useLoaderData(props);\n            return <h1>{data?.message}</h1>;\n          }}\n          loader={loaderFunc}\n        />\n      </MemoryRouter>,\n      container,\n    );\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('renders error on initial', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEXT = 'An error';\n    const loaderFunc = async () => {\n      setDone();\n      throw new Error(TEXT);\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route\n          path=\"/\"\n          render={(props: any) => {\n            const err = useLoaderError(props);\n            return <h1>{err?.message}</h1>;\n          }}\n          loader={loaderFunc}\n        />\n      </MemoryRouter>,\n      container,\n    );\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('Can access initialData (for hydration)', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n\n    const initialData = {\n      '/flowers': { res: await loaderFunc(), err: undefined },\n    };\n\n    history.replaceState(undefined, '', '/flowers');\n    render(\n      <BrowserRouter initialData={initialData}>\n        <Route path=\"/flowers\" render={Component} loader={loaderFunc} />\n      </BrowserRouter>,\n      container,\n    );\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('Should render component after after click', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n    const TEST = 'ok';\n    const loaderFunc = async () => {\n      setDone();\n      return { message: TEST };\n    };\n\n    function RootComp() {\n      return <div id=\"root\">ROOT</div>;\n    }\n\n    function CreateComp(props) {\n      const res = useLoaderData(props);\n      return <div id=\"create\">{res.message}</div>;\n    }\n\n    function PublishComp() {\n      return <div id=\"publish\">PUBLISH</div>;\n    }\n\n    const tree = (\n      <BrowserRouter>\n        <div>\n          <nav>\n            <ul>\n              <li>\n                <NavLink exact to=\"/\">\n                  Play\n                </NavLink>\n              </li>\n              <li id=\"createNav\">\n                <NavLink to=\"/create\">Create</NavLink>\n              </li>\n              <li>\n                <NavLink to=\"/publish\">Publish</NavLink>\n              </li>\n            </ul>\n          </nav>\n          <Route exact path=\"/\" component={RootComp} />\n          <Route path=\"/create\" component={CreateComp} loader={loaderFunc} />\n          <Route path=\"/publish\" component={PublishComp} />\n        </div>\n      </BrowserRouter>\n    );\n\n    render(tree, container);\n\n    expect(container.innerHTML).toContain('ROOT');\n\n    // Click create\n    const link = container.querySelector('#createNav');\n    link.firstChild.click();\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.querySelector('#create').innerHTML).toContain(TEST);\n  });\n\n  it('calls json() when response is received', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEXT = 'ok';\n    const loaderFunc = async () => {\n      setDone();\n      const data = { message: TEXT };\n      return createResponse(data, 'json', 200);\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route\n          path=\"/\"\n          render={(props: any) => {\n            const data = useLoaderData(props);\n            return <h1>{data?.message}</h1>;\n          }}\n          loader={loaderFunc}\n        />\n      </MemoryRouter>,\n      container,\n    );\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('calls text() when response is received', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEXT = 'ok';\n    const loaderFunc = async () => {\n      setDone();\n      const data = TEXT;\n      return createResponse(data, 'text', 200);\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route\n          path=\"/\"\n          render={(props: any) => {\n            const data = useLoaderData(props);\n            return <h1>{data}</h1>;\n          }}\n          loader={loaderFunc}\n        />\n      </MemoryRouter>,\n      container,\n    );\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n});\n\ndescribe('A <Route> with loader in a StaticRouter', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n    // Reset history to root\n    history.replaceState(undefined, '', '/');\n  });\n\n  it('renders on initial', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEXT = 'ok';\n    const loaderFunc = async () => {\n      setDone();\n      return { message: TEXT };\n    };\n\n    render(\n      <StaticRouter context={{}}>\n        <Route\n          path=\"/\"\n          render={(props: any) => {\n            const data = useLoaderData(props);\n            return <h1>{data?.message}</h1>;\n          }}\n          loader={loaderFunc}\n        />\n      </StaticRouter>,\n      container,\n    );\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('renders error on initial', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEXT = 'An error';\n    const loaderFunc = async () => {\n      setDone();\n      throw new Error(TEXT);\n    };\n\n    render(\n      <StaticRouter context={{}}>\n        <Route\n          path=\"/\"\n          render={(props: any) => {\n            const err = useLoaderError(props);\n            return <h1>{err?.message}</h1>;\n          }}\n          loader={loaderFunc}\n        />\n      </StaticRouter>,\n      container,\n    );\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('Can access initialData (for hydration)', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n\n    const initialData = {\n      '/flowers': { res: await loaderFunc(), err: undefined },\n    };\n\n    render(\n      <StaticRouter context={{}} location=\"/flowers\" initialData={initialData}>\n        <Route path=\"/flowers\" render={Component} loader={loaderFunc} />\n      </StaticRouter>,\n      container,\n    );\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n});\n\ndescribe('Resolve loaders during server side rendering', () => {\n  it('Can resolve with single route', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n\n    const initialData = {\n      '/flowers': { res: await loaderFunc() },\n    };\n\n    const app = (\n      <StaticRouter context={{}} location=\"/flowers\">\n        <Route path=\"/flowers\" render={Component} loader={loaderFunc} />\n      </StaticRouter>\n    );\n\n    const loaderEntries = traverseLoaders('/flowers', app);\n    const result = await resolveLoaders(loaderEntries);\n    expect(result).toEqual(initialData);\n  });\n\n  it('Can resolve with multiple routes', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n\n    const loaderFuncNoHit = async () => {\n      return { message: 'no' };\n    };\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n\n    const initialData = {\n      '/birds': { res: await loaderFunc() },\n    };\n\n    const app = (\n      <StaticRouter context={{}} location=\"/birds\">\n        <Route path=\"/flowers\" render={Component} loader={loaderFuncNoHit} />\n        <Route path=\"/birds\" render={Component} loader={loaderFunc} />\n        <Route path=\"/bees\" render={Component} loader={loaderFuncNoHit} />\n      </StaticRouter>\n    );\n\n    const loaderEntries = traverseLoaders('/birds', app);\n    const result = await resolveLoaders(loaderEntries);\n    expect(result).toEqual(initialData);\n  });\n\n  it('Can resolve with nested routes', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n\n    const loaderFuncNoHit = async () => {\n      return { message: 'no' };\n    };\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n\n    const initialData = {\n      '/flowers': { res: await loaderFunc() },\n      '/flowers/birds': { res: await loaderFunc() },\n    };\n\n    const app = (\n      <StaticRouter context={{}} location=\"/flowers/birds\">\n        <Route path=\"/flowers\" render={Component} loader={loaderFunc}>\n          <Route path=\"/flowers/birds\" render={Component} loader={loaderFunc} />\n          <Route\n            path=\"/flowers/bees\"\n            render={Component}\n            loader={loaderFuncNoHit}\n          />\n          {null}\n        </Route>\n      </StaticRouter>\n    );\n\n    const loaderEntries = traverseLoaders('/flowers/birds', app);\n    const result = await resolveLoaders(loaderEntries);\n    expect(result).toEqual(initialData);\n  });\n\n  it('Can resolve with sub classed Route', async () => {\n    class MyRoute extends Route {\n      constructor(props, context) {\n        super(props, context);\n      }\n    }\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n\n    const loaderFuncNoHit = async () => {\n      return { message: 'no' };\n    };\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n\n    const initialData = {\n      '/flowers': { res: await loaderFunc() },\n      '/flowers/birds': { res: await loaderFunc() },\n    };\n\n    const app = (\n      <StaticRouter context={{}} location=\"/flowers/birds\">\n        <MyRoute path=\"/flowers\" render={Component} loader={loaderFunc}>\n          <MyRoute\n            path=\"/flowers/birds\"\n            render={Component}\n            loader={loaderFunc}\n          />\n          <MyRoute\n            path=\"/flowers/bees\"\n            render={Component}\n            loader={loaderFuncNoHit}\n          />\n          {null}\n        </MyRoute>\n      </StaticRouter>\n    );\n\n    const loaderEntries = traverseLoaders('/flowers/birds', app);\n    const result = await resolveLoaders(loaderEntries);\n    expect(result).toEqual(initialData);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/loaderWithSwitch.spec.tsx",
    "content": "import { render, rerender } from 'inferno';\nimport {\n  MemoryRouter,\n  StaticRouter,\n  Route,\n  Switch,\n  NavLink,\n  useLoaderData,\n  useLoaderError,\n  resolveLoaders,\n  traverseLoaders,\n} from 'inferno-router';\n// Cherry picked relative import so we don't get node-stuff from inferno-server in browser test\nimport { createEventGuard } from './testUtils';\n\ndescribe('A <Route> with loader in a MemoryRouter', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('renders on initial', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEXT = 'ok';\n    const loaderFunc = async () => {\n      setDone();\n      return { message: TEXT };\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route\n          path=\"/\"\n          render={(props: any) => {\n            const data = useLoaderData(props);\n            return <h1>{data?.message}</h1>;\n          }}\n          loader={loaderFunc}\n        />\n      </MemoryRouter>,\n      container,\n    );\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('renders error on initial', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEXT = 'An error';\n    const loaderFunc = async () => {\n      setDone();\n      throw new Error(TEXT);\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/']}>\n        <Route\n          path=\"/\"\n          render={(props: any) => {\n            const err = useLoaderError(props);\n            return <h1>{err?.message}</h1>;\n          }}\n          loader={loaderFunc}\n        />\n      </MemoryRouter>,\n      container,\n    );\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('Can access initialData (for hydration)', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n    const initialData = {\n      '/flowers': { res: await loaderFunc(), err: undefined },\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/flowers']} initialData={initialData}>\n        <Route path=\"/flowers\" render={Component} loader={loaderFunc} />\n      </MemoryRouter>,\n      container,\n    );\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('Should render component after click', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEST = 'ok';\n    const loaderFunc = async () => {\n      setDone();\n      return { message: TEST };\n    };\n\n    function RootComp() {\n      return <div id=\"root\">ROOT</div>;\n    }\n\n    function CreateComp(props) {\n      const res = useLoaderData(props);\n      return <div id=\"create\">{res.message}</div>;\n    }\n\n    function PublishComp() {\n      return <div id=\"publish\">PUBLISH</div>;\n    }\n\n    const tree = (\n      <MemoryRouter>\n        <div>\n          <nav>\n            <ul>\n              <li>\n                <NavLink exact to=\"/\">\n                  Play\n                </NavLink>\n              </li>\n              <li id=\"createNav\">\n                <NavLink to=\"/create\">Create</NavLink>\n              </li>\n              <li>\n                <NavLink to=\"/publish\">Publish</NavLink>\n              </li>\n            </ul>\n          </nav>\n          <Switch>\n            <Route exact path=\"/\" component={RootComp} />\n            <Route path=\"/create\" component={CreateComp} loader={loaderFunc} />\n            <Route path=\"/publish\" component={PublishComp} />\n          </Switch>\n        </div>\n      </MemoryRouter>\n    );\n\n    render(tree, container);\n\n    expect(container.innerHTML).toContain('ROOT');\n\n    // Click create\n    const link = container.querySelector('#createNav');\n    link.firstChild.click();\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.querySelector('#create').innerHTML).toContain(TEST);\n  });\n\n  it('Can access initialData (for hydration)', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n    const initialData = {\n      '/flowers': { res: await loaderFunc(), err: undefined },\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/flowers']} initialData={initialData}>\n        <Route path=\"/flowers\" render={Component} loader={loaderFunc} />\n      </MemoryRouter>,\n      container,\n    );\n\n    expect(container.innerHTML).toContain(TEXT);\n  });\n\n  it('Should only render one (1) component after click', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEST = 'ok';\n    const loaderFunc = async () => {\n      setDone();\n      return { message: TEST };\n    };\n\n    function RootComp() {\n      return <div id=\"root\">ROOT</div>;\n    }\n\n    function CreateComp(props) {\n      const res = useLoaderData(props);\n      return <div id=\"create\">{res.message}</div>;\n    }\n\n    function PublishComp() {\n      return <div id=\"publish\">PUBLISH</div>;\n    }\n\n    const tree = (\n      <MemoryRouter>\n        <div>\n          <nav>\n            <ul>\n              <li>\n                <NavLink exact to=\"/\">\n                  Play\n                </NavLink>\n              </li>\n              <li id=\"createNav\">\n                <NavLink to=\"/create\">Create</NavLink>\n              </li>\n              <li>\n                <NavLink to=\"/publish\">Publish</NavLink>\n              </li>\n            </ul>\n          </nav>\n          <Switch>\n            <Route exact path=\"/\" component={RootComp} />\n            <Route path=\"/create\" component={CreateComp} loader={loaderFunc} />\n            <Route path=\"/create\" component={PublishComp} />\n          </Switch>\n        </div>\n      </MemoryRouter>\n    );\n\n    render(tree, container);\n\n    expect(container.innerHTML).toContain('ROOT');\n\n    // Click create\n    const link = container.querySelector('#createNav');\n    link.firstChild.click();\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.querySelector('#create').innerHTML).toContain(TEST);\n    expect(container.querySelector('#publish')).toBeNull();\n  });\n\n  it('can use a `location` prop instead of `router.location`', async () => {\n    const [setSwitch, waitForSwitch] = createEventGuard();\n    const [setDone, waitForRerender] = createEventGuard();\n\n    const TEST = 'ok';\n    const loaderFunc = async () => {\n      await waitForSwitch();\n      setDone();\n      return { message: TEST };\n    };\n\n    render(\n      <MemoryRouter initialEntries={['/one']}>\n        <NavLink id=\"link\" to=\"/two\">\n          Link\n        </NavLink>\n        <Switch>\n          <Route path=\"/one\" render={() => <h1>one</h1>} />\n          <Route\n            path=\"/two\"\n            render={(props: any) => {\n              const res = useLoaderData(props);\n              return <h1>{res.message}</h1>;\n            }}\n            loader={loaderFunc}\n          />\n        </Switch>\n      </MemoryRouter>,\n      container,\n    );\n\n    // Check that we are starting in the right place\n    expect(container.innerHTML).toContain('one');\n\n    const link = container.querySelector('#link');\n    link.click();\n\n    // Complete any pending render and make sure we don't\n    // prematurely update view\n    rerender();\n    expect(container.innerHTML).toContain('one');\n    // Now loader can be allowed to complete\n\n    setSwitch();\n    // and now wait for the loader to complete\n    await waitForRerender();\n    // so /two is rendered\n    expect(container.innerHTML).toContain(TEST);\n  });\n\n  it('Should only render one (1) component after click with subclass of Switch', async () => {\n    const [setDone, waitForRerender] = createEventGuard();\n\n    class SubSwitch extends Switch {}\n\n    const TEST = 'ok';\n    const loaderFunc = async () => {\n      setDone();\n      return { message: TEST };\n    };\n\n    function RootComp() {\n      return <div id=\"root\">ROOT</div>;\n    }\n\n    function CreateComp(props) {\n      const res = useLoaderData(props);\n      return <div id=\"create\">{res.message}</div>;\n    }\n\n    function PublishComp() {\n      return <div id=\"publish\">PUBLISH</div>;\n    }\n\n    const tree = (\n      <MemoryRouter>\n        <div>\n          <nav>\n            <ul>\n              <li>\n                <NavLink exact to=\"/\">\n                  Play\n                </NavLink>\n              </li>\n              <li id=\"createNav\">\n                <NavLink to=\"/create\">Create</NavLink>\n              </li>\n              <li>\n                <NavLink to=\"/publish\">Publish</NavLink>\n              </li>\n            </ul>\n          </nav>\n          <SubSwitch>\n            <Route exact path=\"/\" component={RootComp} />\n            <Route path=\"/create\" component={CreateComp} loader={loaderFunc} />\n            <Route path=\"/create\" component={PublishComp} />\n          </SubSwitch>\n        </div>\n      </MemoryRouter>\n    );\n\n    render(tree, container);\n\n    expect(container.innerHTML).toContain('ROOT');\n\n    // Click create\n    const link = container.querySelector('#createNav');\n    link.firstChild.click();\n\n    // Wait until async loader has completed\n    await waitForRerender();\n\n    expect(container.querySelector('#create').innerHTML).toContain(TEST);\n    expect(container.querySelector('#publish')).toBeNull();\n  });\n});\n\ndescribe('Resolve loaders during server side rendering', () => {\n  it('Can resolve with single route', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n\n    const initialData = {\n      '/flowers': { res: await loaderFunc() },\n    };\n\n    const app = (\n      <StaticRouter context={{}} location=\"/flowers\">\n        <Switch>\n          <Route path=\"/flowers\" render={Component} loader={loaderFunc} />\n        </Switch>\n      </StaticRouter>\n    );\n\n    const loaderEntries = traverseLoaders('/flowers', app);\n    const result = await resolveLoaders(loaderEntries);\n    expect(result).toEqual(initialData);\n  });\n\n  it('Can resolve with multiple routes', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n\n    const loaderFuncNoHit = async () => {\n      return { message: 'no' };\n    };\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n\n    const initialData = {\n      '/birds': { res: await loaderFunc() },\n    };\n\n    const app = (\n      <StaticRouter context={{}} location=\"/birds\">\n        <Switch>\n          <Route path=\"/flowers\" render={Component} loader={loaderFuncNoHit} />\n          <Route path=\"/birds\" render={Component} loader={loaderFunc} />\n          <Route path=\"/birds\" render={Component} loader={loaderFuncNoHit} />\n        </Switch>\n      </StaticRouter>\n    );\n\n    const loaderEntries = traverseLoaders('/birds', app);\n    const result = await resolveLoaders(loaderEntries);\n    expect(result).toEqual(initialData);\n  });\n\n  it('Can resolve with nested routes', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n\n    const loaderFuncNoHit = async () => {\n      return { message: 'no' };\n    };\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n\n    const initialData = {\n      '/flowers': { res: await loaderFunc() },\n      '/flowers/birds': { res: await loaderFunc() },\n    };\n\n    const app = (\n      <StaticRouter context={{}} location=\"/flowers/birds\">\n        <Route path=\"/flowers\" render={Component} loader={loaderFunc}>\n          <Switch>\n            <Route\n              path=\"/flowers/birds\"\n              render={Component}\n              loader={loaderFunc}\n            />\n            <Route\n              path=\"/flowers/bees\"\n              render={Component}\n              loader={loaderFuncNoHit}\n            />\n            {null}\n          </Switch>\n        </Route>\n      </StaticRouter>\n    );\n\n    const loaderEntries = traverseLoaders('/flowers/birds', app);\n    const result = await resolveLoaders(loaderEntries);\n    expect(result).toEqual(initialData);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/matchPath.spec.ts",
    "content": "import { matchPath } from 'inferno-router';\n\ndescribe('matchPath', () => {\n  describe('with path=\"/\"', () => {\n    it('returns correct url at \"/\"', () => {\n      const path = '/';\n      const pathname = '/';\n      const match = matchPath(pathname, path);\n      expect(match?.url).toBe('/');\n    });\n\n    it('returns correct url at \"/somewhere/else\"', () => {\n      const path = '/';\n      const pathname = '/somewhere/else';\n      const match = matchPath(pathname, path);\n      expect(match?.url).toBe('/');\n    });\n  });\n\n  describe('with path=\"/somewhere\"', () => {\n    it('returns correct url at \"/somewhere\"', () => {\n      const path = '/somewhere';\n      const pathname = '/somewhere';\n      const match = matchPath(pathname, path);\n      expect(match?.url).toBe('/somewhere');\n    });\n\n    it('returns correct url at \"/somewhere/else\"', () => {\n      const path = '/somewhere';\n      const pathname = '/somewhere/else';\n      const match = matchPath(pathname, path);\n      expect(match?.url).toBe('/somewhere');\n    });\n  });\n\n  describe('with sensitive path', () => {\n    it('returns non-sensitive url', () => {\n      const options = {\n        path: '/SomeWhere',\n      };\n      const pathname = '/somewhere';\n      const match = matchPath(pathname, options);\n      expect(match?.url).toBe('/somewhere');\n    });\n\n    it('returns sensitive url', () => {\n      const options = {\n        path: '/SomeWhere',\n        sensitive: true,\n      };\n      const pathname = '/somewhere';\n      const match = matchPath(pathname, options);\n      expect(match).toBe(null);\n    });\n  });\n\n  describe('with no path', () => {\n    it('matches the root URL', () => {\n      const match = matchPath('/test-location/7', {});\n      expect(match?.path).toBe('/');\n      expect(match?.url).toBe('/');\n      expect(match?.isExact).toBe(false);\n      expect(match?.params).toEqual({});\n    });\n  });\n\n  describe('cache', () => {\n    it('creates a cache entry for each exact/strict pair', () => {\n      // true/false and false/true will collide when adding booleans\n      const trueFalse = matchPath('/one/two', {\n        exact: true,\n        path: '/one/two/',\n        strict: false,\n      });\n      const falseTrue = matchPath('/one/two', {\n        exact: false,\n        path: '/one/two/',\n        strict: true,\n      });\n      expect(!!trueFalse).toBe(true);\n      expect(!!falseTrue).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/mobx-router.spec.tsx",
    "content": "import { Component, render } from 'inferno';\nimport { inject, observer, Provider } from 'inferno-mobx';\nimport { Route, Router } from 'inferno-router';\nimport { createMemoryHistory } from 'history';\nimport { action, observable } from 'mobx';\n\ndescribe('Github #1236', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('Should not patch twice', () => {\n    /*\n       This is pre-compiled from old decorator pattern\n     */\n    const _createClass = (function () {\n      function defineProperties(target, props) {\n        for (let i = 0; i < props.length; i++) {\n          const descriptor = props[i];\n          descriptor.enumerable = descriptor.enumerable || false;\n          descriptor.configurable = true;\n          if ('value' in descriptor) descriptor.writable = true;\n          Object.defineProperty(target, descriptor.key, descriptor);\n        }\n      }\n      return function (Constructor, protoProps, staticProps = undefined) {\n        if (protoProps) defineProperties(Constructor.prototype, protoProps);\n        if (staticProps) defineProperties(Constructor, staticProps);\n        return Constructor;\n      };\n    })();\n\n    function _initDefineProp(target, property, descriptor, context) {\n      if (!descriptor) return;\n      Object.defineProperty(target, property, {\n        configurable: descriptor.configurable,\n        enumerable: descriptor.enumerable,\n        value: descriptor.initializer\n          ? descriptor.initializer.call(context)\n          : void 0,\n        writable: descriptor.writable,\n      });\n    }\n\n    function _classCallCheck(instance, Constructor) {\n      if (!(instance instanceof Constructor)) {\n        throw new TypeError('Cannot call a class as a function');\n      }\n    }\n\n    function _applyDecoratedDescriptor(\n      target,\n      property,\n      decorators,\n      descriptor,\n      context?,\n    ) {\n      let desc: any = {};\n      for (const key of Object['ke' + 'ys'](descriptor)) {\n        desc[key] = descriptor[key];\n      }\n      desc.enumerable = !!desc.enumerable;\n      desc.configurable = !!desc.configurable;\n\n      if ('value' in desc || desc.initializer) {\n        desc.writable = true;\n      }\n\n      desc = decorators\n        .slice()\n        .reverse()\n        .reduce(function (descIn, decorator) {\n          return decorator(target, property, descIn) || descIn;\n        }, desc);\n\n      if (context && desc.initializer !== void 0) {\n        desc.value = desc.initializer ? desc.initializer.call(context) : void 0;\n        desc.initializer = undefined;\n      }\n\n      if (desc.initializer === void 0) {\n        Object['define' + 'Property'](target, property, desc);\n        desc = null;\n      }\n\n      return desc;\n    }\n    let _class;\n    let _descriptor;\n    const SearchStore =\n      ((_class = (function () {\n        function TestSearchStore() {\n          _classCallCheck(this, TestSearchStore);\n\n          _initDefineProp(this, 'query', _descriptor, this);\n        }\n\n        _createClass(TestSearchStore, [\n          {\n            key: 'doSearch',\n            value: function doSearch(search) {\n              this.query = search;\n            },\n          },\n        ]);\n\n        return TestSearchStore;\n      })()),\n      ((_descriptor = _applyDecoratedDescriptor(\n        _class.prototype,\n        'query',\n        [observable],\n        {\n          enumerable: true,\n          initializer: function initializer() {\n            return undefined;\n          },\n        },\n      )),\n      _applyDecoratedDescriptor(\n        _class.prototype,\n        'doSearch',\n        [action],\n        Object.getOwnPropertyDescriptor(_class.prototype, 'doSearch'),\n        _class.prototype,\n      )),\n      _class);\n\n    let SearchPage = observer(\n      class TestSearchPage extends Component {\n        constructor(props) {\n          super(props);\n          this.doSearch = this.doSearch.bind(this);\n        }\n\n        public componentWillReceiveProps(nextProps) {\n          nextProps.searchStore.doSearch(nextProps.location.search);\n        }\n\n        public doSearch(e) {\n          e.preventDefault();\n          const nextLoc =\n            this.context.router.history.location.pathname + '?q=test';\n          this.context.router.history.push(nextLoc);\n        }\n\n        public render({ searchStore: searchStoreIn }: any) {\n          const showView = searchStoreIn.query ? 'results' : 'default';\n\n          return (\n            <div key=\"search-container\">\n              <a key=\"asd\" id=\"test-btn\" href=\"#front\" onClick={this.doSearch}>\n                link\n              </a>\n              {showView === 'default' && (\n                <div key=\"search-default\">default</div>\n              )}\n              {showView === 'results' && <SearchResult key=\"search-results\" />}\n            </div>\n          );\n        }\n      },\n    );\n\n    SearchPage = inject('searchStore')(SearchPage);\n\n    class SearchResult extends Component {\n      public render() {\n        return <div>results</div>;\n      }\n    }\n\n    /**\n     * Routing\n     */\n    const searchStore = new SearchStore();\n    const memHistory = createMemoryHistory();\n\n    const appRoutes = (\n      <Provider searchStore={searchStore}>\n        <Router history={memHistory}>\n          <Route component={SearchPage} />\n        </Router>\n      </Provider>\n    );\n\n    render(appRoutes, container);\n\n    expect(container.innerHTML).toEqual(\n      '<div><a id=\"test-btn\" href=\"#front\">link</a><div>default</div></div>',\n    );\n\n    const btn = container.querySelector('#test-btn');\n\n    btn.click();\n\n    expect(container.innerHTML).toEqual(\n      '<div><a id=\"test-btn\" href=\"#front\">link</a><div>results</div></div>',\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/__tests__/testUtils.ts",
    "content": "import { rerender } from 'inferno';\n\nexport function createEventGuard() {\n  const eventState = { done: false };\n  const markEventCompleted = () => {\n    eventState.done = true;\n  };\n  const waitForEventToTriggerRender = async () => {\n    // Wait until event is marked as completed\n    while (!eventState.done) {\n      await new Promise((resolved) => setTimeout(resolved, 1));\n    }\n    // Allow resolving promises to finish\n    await new Promise((resolved) => setTimeout(resolved, 0));\n\n    // Allow render loop to complete\n    rerender();\n  };\n\n  return [markEventCompleted, waitForEventToTriggerRender];\n}\n\nexport function createResponse(data, type, status) {\n  switch (type) {\n    case 'json':\n      return createJsonResponse(data, status);\n    case 'text':\n      if (typeof data !== 'string')\n        throw new Error('Type \"text\" requires string as data');\n      return createTextResponse(data, status);\n    default:\n      throw new Error('Unknown value for param \"type\"');\n  }\n}\n\nfunction createJsonResponse(data, status = 200) {\n  return new MockResponse(data, 'application/json', status);\n}\n\nfunction createTextResponse(data, status = 200) {\n  return new MockResponse(data, 'text/plain', status);\n}\n\nclass MockResponseHeaders {\n  private readonly _headers;\n\n  constructor(headers) {\n    this._headers = headers;\n  }\n\n  public get(key) {\n    return this._headers[key];\n  }\n}\n\nclass MockResponse {\n  private readonly _data: any;\n  private readonly _contentType: string;\n  private readonly _statusCode: number;\n\n  constructor(data, contentType = 'application/json', statusCode = 200) {\n    this._data = data;\n    this._contentType = contentType;\n    this._statusCode = statusCode;\n  }\n\n  get headers() {\n    return new MockResponseHeaders({\n      'Content-Type': this._contentType,\n    });\n  }\n\n  get ok() {\n    return this._statusCode >= 200 && this._statusCode < 300;\n  }\n\n  get type() {\n    return 'basic';\n  }\n\n  get status() {\n    return this._statusCode;\n  }\n\n  public async json() {\n    return await Promise.resolve(this._data);\n  }\n\n  public async text() {\n    return await Promise.resolve(this._data);\n  }\n}\n"
  },
  {
    "path": "packages/inferno-router/__tests__/withRouter.spec.tsx",
    "content": "import { Component, type InfernoNode, render } from 'inferno';\nimport { MemoryRouter, Route, StaticRouter, withRouter } from 'inferno-router';\n\ndescribe('withRouter', () => {\n  let node;\n\n  beforeEach(function () {\n    node = document.createElement('div');\n    document.body.appendChild(node);\n  });\n\n  afterEach(function () {\n    render(null, node);\n    document.body.removeChild(node);\n  });\n\n  it('provides { match, location, history } props', () => {\n    const PropsChecker = withRouter((props) => {\n      expect(typeof props.match).toBe('object');\n      expect(typeof props.location).toBe('object');\n      expect(typeof props.history).toBe('object');\n      return null;\n    });\n\n    render(\n      <MemoryRouter initialEntries={['/bubblegum']}>\n        <Route path=\"/bubblegum\" render={() => <PropsChecker />} />\n      </MemoryRouter>,\n      node,\n    );\n  });\n\n  it('provides the parent match as a prop to the wrapped component', () => {\n    let parentMatch;\n    const PropsChecker = withRouter((props) => {\n      expect(props.match).toEqual(parentMatch);\n      return null;\n    });\n\n    render(\n      <MemoryRouter initialEntries={['/bubblegum']}>\n        <Route\n          path=\"/:flavor\"\n          render={({ match }) => {\n            parentMatch = match;\n            return <PropsChecker />;\n          }}\n        />\n      </MemoryRouter>,\n      node,\n    );\n  });\n\n  describe('inside a <StaticRouter>', () => {\n    it('provides the staticContext prop', () => {\n      const PropsChecker = withRouter((props) => {\n        expect(typeof props.staticContext).toBe('object');\n        expect(props.staticContext).toBe(context);\n        return null;\n      });\n\n      const context = {};\n\n      render(\n        <StaticRouter context={context}>\n          <Route component={PropsChecker} />\n        </StaticRouter>,\n        node,\n      );\n    });\n  });\n\n  it('exposes the wrapped component as WrappedComponent', () => {\n    const TestComponent = (): InfernoNode => <div />;\n    const decorated = withRouter(TestComponent);\n    expect(decorated.WrappedComponent).toBe(TestComponent);\n  });\n\n  it('exposes the instance of the wrapped component via wrappedComponentRef', () => {\n    class WrappedComponent extends Component {\n      public render(): InfernoNode {\n        return null;\n      }\n    }\n    const TestComponent = withRouter(WrappedComponent);\n\n    let ref;\n    render(\n      <MemoryRouter initialEntries={['/bubblegum']}>\n        <Route\n          path=\"/bubblegum\"\n          render={() => (\n            <TestComponent wrappedComponentRef={(r) => (ref = r)} />\n          )}\n        />\n      </MemoryRouter>,\n      node,\n    );\n\n    expect(ref instanceof Component).toBe(true);\n  });\n\n  it('hoists non-react statics from the wrapped component', () => {\n    class TestComponent extends Component {\n      public static hello: string = 'world';\n\n      public static foo(): string {\n        return 'bar';\n      }\n\n      public render(): InfernoNode {\n        return null;\n      }\n    }\n\n    const decorated = withRouter(TestComponent);\n\n    expect(decorated.hello).toBe('world');\n    expect(typeof decorated.foo).toBe('function');\n    expect(decorated.foo()).toBe('bar');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-router/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-router/package.json",
    "content": "{\n  \"name\": \"inferno-router\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Provides routing functionality for Inferno\",\n  \"author\": {\n    \"name\": \"Dominic Gannaway\",\n    \"email\": \"dg@domgan.com\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"files\": [\n    \"index.cjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"keywords\": [\n    \"babel\",\n    \"react\",\n    \"inferno\",\n    \"framework\",\n    \"interfaces\",\n    \"user interfaces\",\n    \"router\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-router\"\n  },\n  \"peerDependencies\": {\n    \"history\": \"^5.3.0\"\n  },\n  \"dependencies\": {\n    \"history\": \"^5.3.0\",\n    \"inferno\": \"9.0.11\",\n    \"path-to-regexp\": \"^1.9.0\"\n  },\n  \"devDependencies\": {\n    \"inferno-server\": \"9.0.11\",\n    \"inferno-vnode-flags\": \"9.0.11\",\n    \"mobx\": \"*\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\"\n    ],\n    \"moduleName\": \"Inferno.Router\",\n    \"moduleGlobals\": {\n      \"inferno\": \"Inferno\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno-router/src/BrowserRouter.ts",
    "content": "import { Component, createComponentVNode, type VNode } from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { createBrowserHistory } from 'history';\nimport { Router, type TLoaderData } from './Router';\nimport { warning } from './utils';\n\nexport interface IBrowserRouterProps {\n  initialData?: Record<string, TLoaderData>;\n  basename?: string;\n  forceRefresh?: boolean;\n  keyLength?: number;\n  children: Array<Component<any, any>>;\n}\n\nexport class BrowserRouter extends Component<IBrowserRouterProps, any> {\n  public history;\n\n  constructor(props?: IBrowserRouterProps, context?: any) {\n    super(props, context);\n    this.history = createBrowserHistory();\n  }\n\n  public render(): VNode {\n    return createComponentVNode(VNodeFlags.ComponentClass, Router, {\n      children: this.props.children,\n      history: this.history,\n      initialData: this.props.initialData,\n    });\n  }\n}\n\nif (process.env.NODE_ENV !== 'production') {\n  BrowserRouter.prototype.componentWillMount = function () {\n    warning(\n      !this.props.history,\n      '<BrowserRouter> ignores the history prop. To use a custom history, ' +\n        'use `import { Router }` instead of `import { BrowserRouter as Router }`.',\n    );\n  };\n}\n"
  },
  {
    "path": "packages/inferno-router/src/HashRouter.ts",
    "content": "import {\n  Component,\n  createComponentVNode,\n  type InfernoNode,\n  type VNode,\n} from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { createHashHistory } from 'history';\nimport { Router } from './Router';\nimport { warning } from './utils';\n\nexport interface IHashRouterProps {\n  children: InfernoNode;\n}\n\nexport class HashRouter extends Component<IHashRouterProps, any> {\n  public history;\n\n  constructor(props?: any, context?: any) {\n    super(props, context);\n    this.history = createHashHistory();\n  }\n\n  public render(): VNode {\n    return createComponentVNode(VNodeFlags.ComponentClass, Router, {\n      children: this.props.children,\n      history: this.history,\n    });\n  }\n}\n\nif (process.env.NODE_ENV !== 'production') {\n  HashRouter.prototype.componentWillMount = function () {\n    warning(\n      !this.props.history,\n      '<HashRouter> ignores the history prop. To use a custom history, ' +\n        'use `import { Router }` instead of `import { HashRouter as Router }`.',\n    );\n  };\n}\n"
  },
  {
    "path": "packages/inferno-router/src/Link.ts",
    "content": "import {\n  createVNode,\n  type Inferno,\n  type InfernoMouseEvent, LinkedEvent,\n  linkEvent,\n  type VNode,\n} from 'inferno';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport { invariant } from './utils';\nimport {isFunction, isString} from 'inferno-shared';\nimport type { Location } from 'history';\nimport { parsePath } from 'history';\nimport { normalizeToLocation, splitLocation } from './locationUtils';\n\nconst isModifiedEvent = (event: InfernoMouseEvent<any>): boolean =>\n  Boolean(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);\n\nexport interface ILinkProps {\n  children?: any;\n  onClick?: ((event: MouseEvent) => void) | LinkedEvent<any, any> | null;\n  target?: string;\n  className?: string;\n  replace?: boolean;\n  to?: string | Partial<Location>; // INVESTIGATE: Should Partial<Location> be Partial<Path> instead since this is what is returned by history.parsePath?\n  innerRef?: any;\n}\n\nfunction handleClick({ props, context }, event: InfernoMouseEvent<any>): void {\n  const onClick = props.onClick;\n  if (onClick) {\n    if (isFunction(onClick)) {\n      onClick(event);\n    } else if (isFunction(onClick.event)) {\n      onClick.event(onClick.data, event);\n    }\n  }\n\n  if (\n    !event.defaultPrevented && // onClick prevented default\n    event.button === 0 && // ignore everything but left clicks\n    !props.target && // let browser handle \"target=_blank\" etc.\n    !isModifiedEvent(event) // ignore clicks with modifier keys\n  ) {\n    event.preventDefault();\n\n    const { history } = context.router;\n    const { replace = false, to: toPropIn } = props;\n    const { to, state } = splitLocation(normalizeToLocation(toPropIn));\n\n    if (replace) {\n      history.replace(to, state);\n    } else {\n      history.push(to, state);\n    }\n  }\n}\n\n/**\n * The public API for rendering a history-aware <a>.\n */\nexport function Link(\n  props: ILinkProps & Inferno.LinkHTMLAttributes<HTMLLinkElement>,\n  context,\n): VNode {\n  // \"replace\" is not purpose left out by spreading the properties\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  const { replace, children, className, to = '', innerRef, ...rest } = props;\n  invariant(context.router, 'You should not use <Link> outside a <Router>');\n\n  const href = context.router.history.createHref(\n    isString(to) ? parsePath(to) : to,\n  );\n  const newProps: any = { ...rest };\n\n  newProps.href = href;\n  newProps.onClick = linkEvent(\n    {\n      context,\n      props,\n    },\n    handleClick,\n  );\n\n  return createVNode(\n    VNodeFlags.HtmlElement,\n    'a',\n    className,\n    children,\n    ChildFlags.UnknownChildren,\n    newProps,\n    null,\n    innerRef,\n  );\n}\n"
  },
  {
    "path": "packages/inferno-router/src/MemoryRouter.ts",
    "content": "import { Component, createComponentVNode, type VNode } from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { createMemoryHistory } from 'history';\nimport { Router, type TLoaderData } from './Router';\nimport { warning } from './utils';\n\nexport interface IMemoryRouterProps {\n  initialEntries?: string[];\n  initialIndex?: number;\n  initialData?: Record<string, TLoaderData>;\n  keyLength?: number;\n  children: Array<Component<any, any>>;\n}\n\nexport class MemoryRouter extends Component<IMemoryRouterProps, any> {\n  public history;\n\n  constructor(props?: IMemoryRouterProps, context?: any) {\n    super(props, context);\n    this.history = createMemoryHistory(props);\n  }\n\n  public render(): VNode {\n    return createComponentVNode(VNodeFlags.ComponentClass, Router, {\n      children: this.props.children,\n      history: this.history,\n      initialData: this.props.initialData,\n    });\n  }\n}\n\nif (process.env.NODE_ENV !== 'production') {\n  MemoryRouter.prototype.componentWillMount = function () {\n    warning(\n      !this.props.history,\n      '<MemoryRouter> ignores the history prop. To use a custom history, ' +\n        'use `import { Router }` instead of `import { MemoryRouter as Router }`.',\n    );\n  };\n}\n"
  },
  {
    "path": "packages/inferno-router/src/NavLink.ts",
    "content": "import { createComponentVNode, type Inferno, type VNode } from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { Route } from './Route';\nimport { type ILinkProps, Link } from './Link';\nimport type { Location } from 'history';\n\nfunction filter(i): any {\n  return i;\n}\n\ninterface NavLinkProps extends Omit<ILinkProps, 'className'> {\n  to: string | Location;\n  exact?: boolean;\n  strict?: boolean;\n  location?: any;\n  activeClassName?: string;\n  className?: string | ((isActive: boolean) => string);\n  activeStyle?: any;\n  style?: object | ((isActive: boolean) => string);\n  isActive?: (match, location) => boolean;\n  ariaCurrent?: string;\n}\n\n/**\n * A <Link> wrapper that knows if it's \"active\" or not.\n */\n\nexport function NavLink({\n  to,\n  exact,\n  strict,\n  onClick,\n  location: linkLocation,\n  activeClassName = 'active',\n  className: classNameProp,\n  activeStyle,\n  style: styleProp,\n  isActive: getIsActive,\n  ariaCurrent = 'true',\n  ...rest\n}: NavLinkProps &\n  Omit<\n    Inferno.LinkHTMLAttributes<HTMLLinkElement>,\n    'className' | 'style'\n  >): any {\n  function linkComponent({ location, match }): VNode {\n    const isActive = Boolean(\n      getIsActive ? getIsActive(match, location) : match,\n    );\n\n    const className =\n      typeof classNameProp === 'function'\n        ? classNameProp(isActive)\n        : classNameProp;\n\n    const style =\n      typeof styleProp === 'function' ? styleProp(isActive) : styleProp;\n\n    return createComponentVNode(VNodeFlags.ComponentFunction, Link, {\n      'aria-current': ((isActive && ariaCurrent) || null) as any,\n      className: isActive\n        ? [className, activeClassName].filter(filter).join(' ')\n        : className,\n      onClick,\n      style: isActive ? { ...style, ...activeStyle } : style,\n      to,\n      ...rest,\n    });\n  }\n\n  return createComponentVNode(VNodeFlags.ComponentClass, Route, {\n    children: linkComponent as any,\n    exact,\n    location: linkLocation,\n    path: typeof to === 'object' ? to.pathname : to,\n    strict,\n  });\n}\n"
  },
  {
    "path": "packages/inferno-router/src/Prompt.ts",
    "content": "import { Component, type InfernoNode } from 'inferno';\nimport { invariant } from './utils';\n\nexport interface IPromptProps {\n  when?: boolean;\n  message: string;\n}\n\n/**\n * The public API for matching a single path and rendering.\n */\nexport class Prompt extends Component<IPromptProps, any> {\n  public unblock;\n\n  public enable(message): void {\n    if (this.unblock) {\n      this.unblock();\n    }\n\n    this.unblock = this.context.router.history.block((tx) => {\n      if (message && window.confirm(message)) {\n        this.unblock();\n        tx.retry();\n      }\n    });\n  }\n\n  public disable(): void {\n    if (this.unblock) {\n      this.unblock();\n      this.unblock = null;\n    }\n  }\n\n  public componentWillMount(): void {\n    invariant(\n      this.context.router,\n      'You should not use <Prompt> outside a <Router>',\n    );\n\n    if (this.props.when) {\n      this.enable(this.props.message);\n    }\n  }\n\n  public componentWillReceiveProps(nextProps): void {\n    if (nextProps.when) {\n      if (!this.props.when || this.props.message !== nextProps.message) {\n        this.enable(nextProps.message);\n      }\n    } else {\n      this.disable();\n    }\n  }\n\n  public componentWillUnmount(): void {\n    this.disable();\n  }\n\n  public render(): InfernoNode {\n    return null;\n  }\n}\n"
  },
  {
    "path": "packages/inferno-router/src/Redirect.ts",
    "content": "import { Component, type InfernoNode } from 'inferno';\nimport { type Location, parsePath, type Path } from 'history';\nimport { combinePath, invariant } from './utils';\nimport { isString } from 'inferno-shared';\n\nexport interface RedirectProps {\n  from?: string;\n  to: string | Partial<Location>;\n  exact?: any;\n  push?: boolean;\n}\n\nfunction getLocationTarget(to): Partial<Path> {\n  if (!isString(to)) {\n    to = combinePath(to);\n  }\n\n  return parsePath(to);\n}\n\nexport class Redirect extends Component<RedirectProps, any> {\n  public isStatic(): boolean {\n    return Boolean(this.context.router?.staticContext);\n  }\n\n  public componentWillMount(): void {\n    invariant(\n      this.context.router,\n      'You should not use <Redirect> outside a <Router>',\n    );\n\n    if (this.isStatic()) {\n      this.perform();\n    }\n  }\n\n  public componentDidMount(): void {\n    if (!this.isStatic()) {\n      this.perform();\n    }\n  }\n\n  public componentDidUpdate(prevProps): void {\n    const prevTo = getLocationTarget(prevProps.to);\n    const nextTo = getLocationTarget(this.props.to);\n\n    if (\n      prevTo.pathname === nextTo.pathname &&\n      prevTo.search === nextTo.search\n    ) {\n      console.error(\n        `You tried to redirect to the same route you're currently on: \"${nextTo.pathname}${nextTo.search}\"`,\n      );\n      return;\n    }\n\n    this.perform();\n  }\n\n  public perform(): void {\n    const { history } = this.context.router;\n    const { push = false, to } = this.props;\n\n    if (push) {\n      history.push(to);\n    } else {\n      history.replace(to);\n    }\n  }\n\n  public render(): InfernoNode {\n    return null;\n  }\n}\n"
  },
  {
    "path": "packages/inferno-router/src/Route.ts",
    "content": "import { Component, createComponentVNode, type InfernoNode } from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { invariant, warning } from './utils';\nimport { matchPath } from './matchPath';\nimport { isFunction, isNullOrUndef, isUndefined } from 'inferno-shared';\nimport type { History, Location } from 'history';\nimport type {\n  RouterContext,\n  TContextRouter,\n  TLoaderData,\n  TLoaderProps,\n} from './Router';\n\nexport interface Match<P extends Record<string, string>> {\n  params: P;\n  isExact: boolean;\n  path: string;\n  url: string;\n  loader?: (props: TLoaderProps<P>) => Promise<any>;\n  loaderData?: TLoaderData;\n}\n\nexport interface RouteComponentProps<P extends Record<string, string>> {\n  match: Match<P>;\n  location: Location;\n  history: History;\n  staticContext?: any;\n}\n\nexport interface IRouteProps {\n  computedMatch?: Match<any> | null; // private, from <Switch>\n  path?: string;\n  exact?: boolean;\n  strict?: boolean;\n  sensitive?: boolean;\n  loader?: (props: TLoaderProps<any>) => Promise<any>;\n  component?:\n    | typeof Component<any, any>\n    | ((props: any, context: any) => InfernoNode);\n  render?: (props: RouteComponentProps<any>, context: any) => InfernoNode;\n  location?: Pick<Location, 'pathname'>;\n  children?: ((props: RouteComponentProps<any>) => InfernoNode) | InfernoNode;\n}\n\n/**\n * The public API for matching a single path and rendering.\n */\ninterface RouteState {\n  match: Match<any> | null;\n  __loaderData__?: TLoaderData;\n}\n\nclass Route extends Component<Partial<IRouteProps>, RouteState> {\n  constructor(props: IRouteProps, context: RouterContext) {\n    super(props, context);\n    const match = this.computeMatch(props, context.router);\n    this.state = {\n      __loaderData__: match?.loaderData,\n      match,\n    };\n  }\n\n  public getChildContext(): RouterContext {\n    const parentRouter: TContextRouter = this.context.router;\n    const router: TContextRouter = { ...parentRouter };\n\n    router.route = {\n      location: this.props.location || parentRouter.route.location,\n      match: this.state!.match,\n    };\n\n    return {\n      router,\n    };\n  }\n\n  public computeMatch(\n    { computedMatch, ...props }: IRouteProps,\n    router: TContextRouter,\n  ): Match<any> | null {\n    if (!isNullOrUndef(computedMatch)) {\n      // <Switch> already computed the match for us\n      return computedMatch;\n    }\n\n    const { path, strict, exact, sensitive, loader } = props;\n\n    if (process.env.NODE_ENV !== 'production') {\n      invariant(\n        router,\n        'You should not use <Route> or withRouter() outside a <Router>',\n      );\n    }\n\n    const { route, initialData } = router; // This is the parent route\n    const pathname = (props.location || route.location).pathname;\n\n    return path\n      ? matchPath(pathname, {\n          path,\n          strict,\n          exact,\n          sensitive,\n          loader,\n          initialData,\n        })\n      : route.match;\n  }\n\n  public componentWillReceiveProps(\n    nextProps,\n    nextContext: { router: TContextRouter },\n  ): void {\n    if (process.env.NODE_ENV !== 'production') {\n      warning(\n        !(nextProps.location && !this.props.location),\n        '<Route> elements should not change from uncontrolled to controlled (or vice versa). You initially used no \"location\" prop and then provided one on a subsequent render.',\n      );\n\n      warning(\n        !(!nextProps.location && this.props.location),\n        '<Route> elements should not change from controlled to uncontrolled (or vice versa). You provided a \"location\" prop initially but omitted it on a subsequent render.',\n      );\n    }\n    const match = this.computeMatch(nextProps, nextContext.router);\n\n    this.setState({\n      __loaderData__: match?.loaderData,\n      match,\n    });\n  }\n\n  public render(\n    props: IRouteProps,\n    state: RouteState,\n    context: { router: TContextRouter },\n  ): InfernoNode {\n    const { match, __loaderData__ } = state;\n    const { children, component, render, loader } = props;\n    const { history, route, staticContext } = context.router;\n    const location = props.location || route.location;\n    const renderProps: any = {\n      match,\n      location,\n      history,\n      staticContext,\n      component,\n      render,\n      loader,\n      __loaderData__,\n    };\n\n    // If we have a loader we don't render until it has been resolved\n    if (!isUndefined(loader) && isUndefined(__loaderData__)) {\n      return null;\n    }\n\n    if (component) {\n      if (process.env.NODE_ENV !== 'production') {\n        if (!isFunction(component)) {\n          throw new Error(\n            \"Inferno error: <Route /> - 'component' property must be prototype of class or functional component, not vNode.\",\n          );\n        }\n      }\n      return match\n        ? createComponentVNode(\n            VNodeFlags.ComponentUnknown,\n            component,\n            renderProps,\n          )\n        : null;\n    }\n\n    if (render) {\n      return match ? render(renderProps, this.context) : null;\n    }\n\n    if (typeof children === 'function') {\n      return (children as Function)(renderProps);\n    }\n\n    return children;\n  }\n}\n\nif (process.env.NODE_ENV !== 'production') {\n  Route.prototype.componentWillMount = function () {\n    warning(\n      !(this.props.component && this.props.render),\n      'You should not use <Route component> and <Route render> in the same route; <Route render> will be ignored',\n    );\n\n    warning(\n      !(this.props.component && this.props.children),\n      'You should not use <Route component> and <Route children> in the same route; <Route children> will be ignored',\n    );\n\n    warning(\n      !(this.props.render && this.props.children),\n      'You should not use <Route render> and <Route children> in the same route; <Route children> will be ignored',\n    );\n  };\n}\n\nexport { Route };\n"
  },
  {
    "path": "packages/inferno-router/src/Router.ts",
    "content": "import { Component, type InfernoNode } from 'inferno';\nimport { isUndefined } from 'inferno-shared';\nimport type { History, Location } from 'history';\nimport { warning } from './utils';\nimport { type Match } from './Route';\nimport { resolveLoaders, traverseLoaders } from './resolveLoaders';\n\nexport interface TLoaderProps<P extends Record<string, string>> {\n  params?: P; // Match params (if any)\n  request: Request; // Fetch API Request\n  // https://github.com/remix-run/react-router/blob/4f3ad7b96e6e0228cc952cd7eafe2c265c7393c7/packages/router/router.ts#L1004\n  // https://github.com/remix-run/react-router/blob/11156ac7f3d7c1c557c67cc449ecbf9bd5c6a4ca/examples/ssr-data-router/src/entry.server.tsx#L66\n  // https://github.com/remix-run/react-router/blob/59b319feaa12745a434afdef5cadfcabd01206f9/examples/search-params/src/App.tsx#L43\n  // https://github.com/remix-run/react-router/blob/11156ac7f3d7c1c557c67cc449ecbf9bd5c6a4ca/packages/react-router-dom/__tests__/data-static-router-test.tsx#L81\n\n  onProgress?: (perc: number) => void;\n}\n\n/**\n * Loader returns Response and throws error\n */\nexport type TLoader<P extends Record<string, string>, R extends Response> = ({\n  params,\n  request,\n}: TLoaderProps<P>) => Promise<R>;\n\nexport interface TLoaderData<Res = any, Err = any> {\n  res?: Res;\n  err?: Err;\n}\n\ntype TInitialData = Record<string, TLoaderData>; // key is route path to allow resolving\n\nexport interface IRouterProps {\n  history: History;\n  children: InfernoNode;\n  initialData?: TInitialData;\n}\n\nexport interface TContextRouter {\n  history: History;\n  route: {\n    location: Pick<Location, 'pathname'>; // This was Partial<Location> before but this makes pathname optional causing false type error in code\n    match: Match<any> | null;\n  };\n  initialData?: TInitialData;\n  staticContext?: object; // TODO: This should be properly typed\n}\n\nexport interface RouterContext {\n  router: TContextRouter;\n}\n\n/**\n * The public API for putting history on context.\n */\nexport class Router extends Component<IRouterProps, any> {\n  public unlisten;\n  private _loaderFetchControllers: AbortController[] = [];\n  private _loaderIteration = 0;\n\n  constructor(props: IRouterProps, context: { router: TContextRouter }) {\n    super(props, context);\n    const match = this.computeMatch(props.history.location.pathname);\n    this.state = {\n      initialData: this.props.initialData,\n      match,\n    };\n  }\n\n  public getChildContext(): RouterContext {\n    const parentRouter: TContextRouter = this.context.router;\n    const router: TContextRouter = { ...parentRouter };\n    router.history = this.props.history;\n    router.route = {\n      location: router.history.location,\n      match: this.state?.match, // Why are we sending this? it appears useless.\n    };\n    router.initialData = this.state?.initialData; // this is a dictionary of all data available\n    return {\n      router,\n    };\n  }\n\n  public computeMatch(pathname): Match<any> {\n    return {\n      isExact: pathname === '/',\n      loader: undefined,\n      params: {},\n      path: '/',\n      url: '/',\n    };\n  }\n\n  public componentWillMount(): void {\n    const { history } = this.props;\n\n    // Do this here so we can setState when a <Redirect> changes the\n    // location in componentWillMount. This happens e.g. when doing\n    // server rendering using a <StaticRouter>.\n    this.unlisten = history.listen(() => {\n      const match = this.computeMatch(history.location.pathname);\n      this._matchAndResolveLoaders(match);\n    });\n\n    // First execution of loaders\n    if (isUndefined(this.props.initialData)) {\n      this._matchAndResolveLoaders(this.state?.match);\n    }\n  }\n\n  private _matchAndResolveLoaders(match?: Match<any>): void {\n    // Keep track of invokation order\n    // Bumping the counter needs to be done first because calling abort\n    // triggers promise to resolve with \"aborted\"\n    this._loaderIteration = (this._loaderIteration + 1) % 10000;\n    const currentIteration = this._loaderIteration;\n\n    for (const controller of this._loaderFetchControllers) {\n      controller.abort();\n    }\n    this._loaderFetchControllers = [];\n\n    const { history, children } = this.props;\n    const loaderEntries = traverseLoaders(history.location.pathname, children);\n    if (loaderEntries.length === 0) {\n      this.setState({ match });\n      return;\n    }\n\n    // Store AbortController instances for each matched loader\n    this._loaderFetchControllers = loaderEntries.map((e) => e.controller);\n\n    void resolveLoaders(loaderEntries).then((initialData): void => {\n      // On multiple pending navigations, only update interface with last\n      // in case they resolve out of order\n      if (currentIteration === this._loaderIteration) {\n        this.setState({\n          initialData,\n          match,\n        });\n      }\n    });\n  }\n\n  public componentWillUnmount(): void {\n    this.unlisten();\n  }\n\n  public render(props: IRouterProps): InfernoNode {\n    return props.children;\n  }\n}\n\nif (process.env.NODE_ENV !== 'production') {\n  Router.prototype.componentWillReceiveProps = function (nextProps) {\n    warning(\n      this.props.history === nextProps.history,\n      'You cannot change <Router history>',\n    );\n  };\n}\n"
  },
  {
    "path": "packages/inferno-router/src/StaticRouter.ts",
    "content": "import {\n  Component,\n  createComponentVNode,\n  type InfernoNode,\n  type Props,\n} from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { Action, type Location, parsePath, type Path } from 'history';\nimport { Router, type TLoaderData } from './Router';\nimport { combinePath, invariant, warning } from './utils';\nimport { isString } from 'inferno-shared';\n\nfunction addLeadingSlash(path: string): string {\n  return path.charAt(0) === '/' ? path : '/' + path;\n}\n\nconst noop = (): void => {};\n\nexport interface IStaticRouterProps<T> extends Props<T> {\n  initialData?: Record<string, TLoaderData>;\n  basename?: string;\n  context: any;\n  location: any;\n}\n\nexport class StaticRouter<P, S> extends Component<\n  P & IStaticRouterProps<any>,\n  S\n> {\n  public static defaultProps: {\n    basename: string;\n    location: Path | string;\n  } = {\n    basename: '',\n    location: '/',\n  };\n\n  public getChildContext(): {\n    router: {\n      initialData?: Record<string, TLoaderData>;\n      staticContext: Record<string, unknown>;\n    };\n  } {\n    return {\n      router: {\n        initialData: this.props.initialData,\n        staticContext: this.props.context,\n      },\n    };\n  }\n\n  public createHref = (path: string): string =>\n    addLeadingSlash((this.props.basename || '') + createURL(path));\n\n  public handlePush = (location): void => {\n    const { basename, context } = this.props;\n    context.action = 'PUSH';\n    context.location = addBasename(\n      basename,\n      isString(location) ? parsePath(location) : location,\n    );\n    context.url = createURL(context.location);\n  };\n\n  public handleReplace = (location): void => {\n    const { basename, context } = this.props;\n    context.action = 'REPLACE';\n    context.location = addBasename(\n      basename,\n      isString(location) ? parsePath(location) : location,\n    );\n    context.url = createURL(context.location);\n  };\n\n  public handleListen = (): (() => void) => noop;\n\n  public handleBlock = (): (() => void) => noop;\n\n  public render({\n    basename,\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    context,\n    location,\n    ...props\n  }: Readonly<\n    { children: InfernoNode } & P & IStaticRouterProps<any>\n  >): InfernoNode {\n    return createComponentVNode(VNodeFlags.ComponentClass, Router, {\n      ...props,\n      history: {\n        action: Action.Pop,\n        block: this.handleBlock,\n        createHref: this.createHref,\n        go: staticHandler('go'),\n        back: staticHandler('goBack'),\n        forward: staticHandler('goForward'),\n        listen: this.handleListen,\n        location: stripBasename(basename, createLocation(location)) as Location,\n        push: this.handlePush,\n        replace: this.handleReplace,\n      },\n    }) as InfernoNode;\n  }\n}\n\nif (process.env.NODE_ENV !== 'production') {\n  StaticRouter.prototype.componentWillMount = function () {\n    warning(\n      !this.props.history,\n      '<StaticRouter> ignores the history prop. To use a custom history, ' +\n        'use `import { Router }` instead of `import { StaticRouter as Router }`.',\n    );\n  };\n}\n\nfunction normalizeLocation({ pathname = '/', search, hash }): Path {\n  return {\n    hash: (hash || '') === '#' ? '' : hash,\n    pathname,\n    search: (search || '') === '?' ? '' : search,\n  };\n}\n\nfunction addBasename(\n  basename: string | null | undefined,\n  location: Location,\n): Location {\n  if (!basename) {\n    return location;\n  }\n\n  return {\n    ...location,\n    pathname: addLeadingSlash(basename) + location.pathname,\n  };\n}\n\nfunction stripBasename(\n  basename: string | undefined | null,\n  location: Path,\n): Path {\n  if (!basename) {\n    return location;\n  }\n\n  const base = addLeadingSlash(basename);\n\n  if (location.pathname.startsWith(base)) {\n    return {\n      ...location,\n      pathname: location.pathname.substring(base.length),\n    };\n  } else {\n    return location;\n  }\n}\n\nfunction createLocation(location): Path {\n  return typeof location === 'string'\n    ? (parsePath(location) as Path)\n    : normalizeLocation(location);\n}\n\nfunction createURL(location): string {\n  return typeof location === 'string' ? location : combinePath(location);\n}\n\nfunction staticHandler(methodName) {\n  return () => {\n    invariant(false, 'You cannot %s with <StaticRouter>', methodName);\n  };\n}\n"
  },
  {
    "path": "packages/inferno-router/src/Switch.ts",
    "content": "import { Component, createComponentVNode, type VNode } from 'inferno';\nimport { matchPath } from './matchPath';\nimport { invariant, warning } from './utils';\nimport { isArray, isInvalid } from 'inferno-shared';\nimport { type IRouteProps, type Match } from './Route';\nimport { type RouterContext } from './Router';\n\nfunction getMatch(\n  pathname: string,\n  { path, exact, strict, sensitive, loader, from },\n  router: { route; initialData?: any },\n): Match<any> | null {\n  path ??= from;\n  const { initialData, route } = router; // This is the parent route\n\n  return path\n    ? matchPath(pathname, {\n        path,\n        exact,\n        strict,\n        sensitive,\n        loader,\n        initialData,\n      })\n    : route.match;\n}\n\ninterface SwitchState {\n  match: Match<any> | null;\n  _child: any;\n}\n\nfunction extractFirstMatchFromChildren(\n  pathname: string,\n  children,\n  router,\n): SwitchState {\n  if (isArray(children)) {\n    for (let i = 0; i < children.length; ++i) {\n      const nestedMatch = extractFirstMatchFromChildren(\n        pathname,\n        children[i],\n        router,\n      );\n      if (nestedMatch.match) {\n        return nestedMatch;\n      }\n    }\n    return {\n      match: null,\n      _child: null,\n    };\n  }\n\n  return {\n    _child: children,\n    match: getMatch(pathname, children.props, router),\n  };\n}\n\nexport class Switch extends Component<IRouteProps, SwitchState> {\n  constructor(props, context: RouterContext) {\n    super(props, context);\n\n    if (process.env.NODE_ENV !== 'production') {\n      invariant(\n        context.router,\n        'You should not use <Switch> outside a <Router>',\n      );\n    }\n\n    const { router } = context;\n    const { location, children } = props;\n    const pathname = (location || router.route.location).pathname;\n    const { match, _child } = extractFirstMatchFromChildren(\n      pathname,\n      children,\n      router,\n    );\n\n    this.state = {\n      _child,\n      match,\n    };\n  }\n\n  public componentWillReceiveProps(\n    nextProps: IRouteProps,\n    nextContext: RouterContext,\n  ): void {\n    if (process.env.NODE_ENV !== 'production') {\n      warning(\n        !(nextProps.location && !this.props.location),\n        '<Switch> elements should not change from uncontrolled to controlled (or vice versa). You initially used no \"location\" prop and then provided one on a subsequent render.',\n      );\n\n      warning(\n        !(!nextProps.location && this.props.location),\n        '<Switch> elements should not change from controlled to uncontrolled (or vice versa). You provided a \"location\" prop initially but omitted it on a subsequent render.',\n      );\n    }\n\n    const { router } = nextContext;\n    const { location, children } = nextProps;\n    const pathname = (location || router.route.location).pathname;\n    const { match, _child } = extractFirstMatchFromChildren(\n      pathname,\n      children,\n      router,\n    );\n\n    this.setState({ match, _child });\n  }\n\n  public render(\n    { children, location }: IRouteProps,\n    { match, _child }: SwitchState,\n    context: RouterContext,\n  ): VNode | null {\n    if (isInvalid(children)) {\n      return null;\n    }\n\n    if (match) {\n      location ??= context.router.route.location;\n      return createComponentVNode(_child.flags, _child.type, {\n        ..._child.props,\n        ...{ location, computedMatch: match },\n      });\n    }\n\n    return null;\n  }\n}\n"
  },
  {
    "path": "packages/inferno-router/src/helpers.ts",
    "content": "import { type TLoaderData } from './Router';\n\nexport function useLoaderData<Res = any>(props: {\n  __loaderData__: TLoaderData<Res, any>;\n}): Res | undefined {\n  return props.__loaderData__?.res;\n}\n\nexport function useLoaderError<Err = any>(props: {\n  __loaderData__: TLoaderData<any, Err>;\n}): Err | undefined {\n  return props.__loaderData__?.err;\n}\n"
  },
  {
    "path": "packages/inferno-router/src/index.ts",
    "content": "import { StaticRouter } from './StaticRouter';\nimport { BrowserRouter } from './BrowserRouter';\nimport { HashRouter } from './HashRouter';\nimport { MemoryRouter } from './MemoryRouter';\nimport { Router } from './Router';\nimport { Route } from './Route';\nimport { Switch } from './Switch';\nimport { Link } from './Link';\nimport { NavLink } from './NavLink';\nimport { Prompt } from './Prompt';\nimport { Redirect } from './Redirect';\nimport { matchPath } from './matchPath';\nimport { withRouter } from './withRouter';\nexport * from './resolveLoaders';\nexport * from './helpers';\n\nexport {\n  BrowserRouter,\n  HashRouter,\n  Link,\n  MemoryRouter,\n  NavLink,\n  Prompt,\n  Redirect,\n  Route,\n  Router,\n  StaticRouter,\n  Switch,\n  matchPath,\n  withRouter,\n};\n"
  },
  {
    "path": "packages/inferno-router/src/locationUtils.ts",
    "content": "import { type Location, parsePath, type To } from 'history';\nimport { isString } from 'inferno-shared';\n\nexport const normalizeToLocation = (to) => {\n  return isString(to) ? parsePath(to) : to;\n};\n\nexport const splitLocation = (location: Location): { to: To; state: any } => {\n  const { state, ...to } = location;\n  return { to, state };\n};\n"
  },
  {
    "path": "packages/inferno-router/src/matchPath.ts",
    "content": "import pathToRegexp from 'path-to-regexp';\nimport { type Match } from './Route';\n\nconst patternCache = {};\nconst cacheLimit = 10000;\nlet cacheCount = 0;\n\ninterface pathToRegexKey {\n  name: string | number;\n  prefix: string;\n  delimiter: string;\n  optional: boolean;\n  repeat: boolean;\n  pattern: string;\n  partial: boolean;\n  asterisk: boolean;\n}\n\nconst compilePath = (pattern, options): { re: any; keys: pathToRegexKey[] } => {\n  const cacheKey = `${options.end}${options.strict}${options.sensitive}`;\n  const cache = patternCache[cacheKey] || (patternCache[cacheKey] = {});\n\n  if (cache[pattern]) {\n    return cache[pattern];\n  }\n\n  const keys = [];\n  const re = pathToRegexp(pattern, keys, options);\n  const compiledPattern = { re, keys };\n\n  if (cacheCount < cacheLimit) {\n    cache[pattern] = compiledPattern;\n    cacheCount++;\n  }\n\n  return compiledPattern;\n};\n\n/**\n * Public API for matching a URL pathname to a path pattern.\n */\nexport function matchPath(pathname, options: any): Match<any> | null {\n  if (typeof options === 'string') {\n    options = { path: options };\n  }\n\n  const {\n    path = '/',\n    exact = false,\n    strict = false,\n    sensitive = false,\n    loader,\n    initialData = {},\n  } = options;\n  const { re, keys } = compilePath(path, { end: exact, strict, sensitive });\n  const match = re.exec(pathname);\n\n  if (!match) {\n    return null;\n  }\n\n  const loaderData = initialData[path];\n\n  const [url, ...values] = match;\n  const isExact = pathname === url;\n\n  if (exact && !isExact) {\n    return null;\n  }\n\n  return {\n    isExact,\n    loader,\n    loaderData,\n    params: keys.reduce((memo, key, index) => {\n      memo[key.name] = values[index];\n      return memo;\n    }, {}),\n    path, // the path pattern used to match\n    url: path === '/' && url === '' ? '/' : url, // the matched portion of the URL\n  };\n}\n"
  },
  {
    "path": "packages/inferno-router/src/resolveLoaders.ts",
    "content": "import { isNullOrUndef, isUndefined } from 'inferno-shared';\nimport { matchPath } from './matchPath';\nimport type { TLoaderData, TLoaderProps } from './Router';\nimport { Switch } from './Switch';\nimport { Route } from './Route';\n\nexport async function resolveLoaders(\n  loaderEntries: TLoaderEntry[],\n): Promise<Record<string, TLoaderData>> {\n  const promises = loaderEntries.map(\n    async ({ path, params, request, loader }) => {\n      return await resolveEntry(path, params, request, loader);\n    },\n  );\n  return await Promise.all(promises).then((result) => {\n    return Object.fromEntries(result);\n  });\n}\n\ninterface TLoaderEntry {\n  path: string;\n  params: Record<string, any>;\n  request: Request;\n  controller: AbortController;\n  loader: (props: TLoaderProps<any>) => Promise<TLoaderEntry>;\n}\n\nexport function traverseLoaders(\n  location: string,\n  tree: any,\n  base?: string,\n): TLoaderEntry[] {\n  return _traverseLoaders(location, tree, base, false);\n}\n\nfunction _isSwitch(node: any): boolean {\n  // Using the same patterns as for _isRoute, but I don't have a test where\n  // I pass a Switch via an array, but it is better to be consistent.\n  return node?.type?.prototype instanceof Switch || node?.type === Switch;\n}\n\nfunction _isRoute(node: any): boolean {\n  // So the === check is needed if routes are passed in an array,\n  // the instanceof test if routes are passed as children to a Component\n  // This feels inconsistent, but at least it works.\n  return node?.type?.prototype instanceof Route || node?.type === Route;\n}\n\n// Optionally pass base param during SSR to get fully qualified request URI passed to loader in request param\nfunction _traverseLoaders(\n  location: string,\n  tree: any,\n  base?: string,\n  parentIsSwitch = false,\n): TLoaderEntry[] {\n  // Make sure tree isn't null\n  if (isNullOrUndef(tree)) return [];\n\n  if (Array.isArray(tree)) {\n    let hasMatch = false;\n    const entriesOfArr = tree.reduce((res, node) => {\n      if (parentIsSwitch && hasMatch) return res;\n\n      const outpArr = _traverseLoaders(location, node, base, _isSwitch(node));\n      if (parentIsSwitch && outpArr.length > 0) {\n        hasMatch = true;\n      }\n      return [...res, ...outpArr];\n    }, []);\n    return entriesOfArr;\n  }\n\n  const outp: TLoaderEntry[] = [];\n  if (_isRoute(tree) && tree.props) {\n    // TODO: Should we check if we are in Router? It is defensive and could save a bit of time, but is it worth it?\n    const {\n      path,\n      exact = false,\n      strict = false,\n      sensitive = false,\n    } = tree.props;\n    const match = matchPath(location, {\n      exact,\n      path,\n      sensitive,\n      strict,\n    });\n\n    // So we can bail out of recursion it this was a Route which didn't match\n    if (!match) {\n      return outp;\n    } else if (!tree.context && tree.props?.loader && tree.props?.path) {\n      // Add any loader on this node (but only on the VNode)\n      const { params } = match;\n      const controller = new AbortController();\n      const request = createClientSideRequest(\n        location,\n        controller.signal,\n        base,\n      );\n\n      outp.push({\n        controller,\n        loader: tree.props.loader,\n        params,\n        path,\n        request,\n      });\n    }\n  }\n\n  // Traverse children\n  const children = tree.children ?? tree.props?.children;\n  if (isNullOrUndef(children)) return outp;\n\n  const entries = _traverseLoaders(location, children, base, _isSwitch(tree));\n  return [...outp, ...entries];\n}\n\nasync function resolveEntry(path, params, request, loader): Promise<any> {\n  return (\n    loader({ params, request })\n      .then(async (res: any) => {\n        // This implementation is based on:\n        // https://github.com/remix-run/react-router/blob/4f3ad7b96e6e0228cc952cd7eafe2c265c7393c7/packages/router/router.ts#L2787-L2879\n\n        // Check if regular data object (from tests or initialData)\n        if (typeof res.json !== 'function') {\n          return [path, { res }];\n        }\n\n        const contentType = res.headers.get('Content-Type');\n        let dataPromise: Promise<any>;\n        // Check between word boundaries instead of startsWith() due to the last\n        // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type\n        if (contentType && /\\bapplication\\/json\\b/.test(contentType)) {\n          dataPromise = res.json();\n        } else {\n          dataPromise = res.text();\n        }\n\n        return await dataPromise\n          .then((body) => {\n            // We got a JSON error\n            if (!res.ok) {\n              return [path, { err: body }];\n            }\n            // We got JSON response\n            return [path, { res: body }];\n          })\n          // Could not parse JSON\n          .catch((err) => [path, { err }]);\n      })\n      // Could not fetch data\n      .catch((err) => [path, { err }])\n  );\n}\n\n// From react-router\n// NOTE: We don't currently support the submission param of createClientSideRequest which is why\n// some of the related code is commented away\n\nexport type FormEncType =\n  | 'application/x-www-form-urlencoded'\n  | 'multipart/form-data';\n\nexport type MutationFormMethod = 'post' | 'put' | 'patch' | 'delete';\nexport type FormMethod = 'get' | MutationFormMethod;\n\n// TODO: react-router supports submitting forms with loaders, this is related to that\n// const validMutationMethodsArr: MutationFormMethod[] = [\n//   \"post\",\n//   \"put\",\n//   \"patch\",\n//   \"delete\",\n// ];\n// const validMutationMethods = new Set<MutationFormMethod>(\n//   validMutationMethodsArr\n// );\n\n/**\n * @private\n * Internal interface to pass around for action submissions, not intended for\n * external consumption\n */\nexport interface Submission {\n  formMethod: FormMethod;\n  formAction: string;\n  formEncType: FormEncType;\n  formData: FormData;\n}\n\nconst inBrowser = typeof window === 'undefined';\nfunction createClientSideRequest(\n  location: string | Location,\n  signal: AbortSignal,\n  // submission?: Submission\n  base?: string,\n): Request {\n  const url =\n    inBrowser || !isUndefined(base)\n      ? createClientSideURL(location, base)\n      : location.toString();\n  const init: RequestInit = { signal };\n\n  // TODO: react-router supports submitting forms with loaders, but this needs more investigation\n  // related code is commented out in this file\n  // if (submission && isMutationMethod(submission.formMethod)) {\n  //   let { formMethod, formEncType, formData } = submission;\n  //   init.method = formMethod.toUpperCase();\n  //   init.body =\n  //     formEncType === \"application/x-www-form-urlencoded\"\n  //       ? convertFormDataToSearchParams(formData)\n  //       : formData;\n  // }\n\n  // Request is undefined when running tests\n  if (process.env.NODE_ENV === 'test' && typeof Request === 'undefined') {\n    // @ts-expect-error minimum to fix tests\n    global.Request = class Request {\n      public url;\n      public signal;\n      constructor(_url: URL | string, _init: RequestInit) {\n        this.url = _url;\n        this.signal = _init.signal;\n      }\n    };\n  }\n\n  // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n  return new Request(url, init);\n}\n\n/**\n * Parses a string URL path into its separate pathname, search, and hash components.\n */\n\nexport function createClientSideURL(\n  location: Location | string,\n  base?: string,\n): URL {\n  if (base === undefined && typeof window !== 'undefined') {\n    // window.location.origin is \"null\" (the literal string value) in Firefox\n    // under certain conditions, notably when serving from a local HTML file\n    // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297\n    base =\n      window?.location?.origin !== 'null'\n        ? window.location.origin\n        : window.location.href;\n  }\n\n  const url = new URL(location.toString(), base);\n  url.hash = '';\n  return url;\n}\n\n// TODO: react-router supports submitting forms with loaders, this is related to that\n// function isMutationMethod(method?: string): method is MutationFormMethod {\n//   return validMutationMethods.has(method as MutationFormMethod);\n// }\n\n// function convertFormDataToSearchParams(formData: FormData): URLSearchParams {\n//   let searchParams = new URLSearchParams();\n\n//   for (let [key, value] of formData.entries()) {\n//     // invariant(\n//     //   typeof value === \"string\",\n//     //   'File inputs are not supported with encType \"application/x-www-form-urlencoded\", ' +\n//     //     'please use \"multipart/form-data\" instead.'\n//     // );\n//     if (typeof value === \"string\") {\n//       searchParams.append(key, value);\n//     }\n//   }\n\n//   return searchParams;\n// }\n"
  },
  {
    "path": "packages/inferno-router/src/utils.ts",
    "content": "import { type Path } from 'history';\n\nexport function warning(condition, message): void {\n  if (!condition) {\n    console.error(message);\n  }\n}\n\nexport function combinePath({\n  pathname = '/',\n  search = '',\n  hash = '',\n}: Partial<Path>): string {\n  return pathname + search + hash;\n}\n\nexport function invariant(condition, format, a?, b?, c?, d?, e?, f?): void {\n  if (!condition) {\n    let error;\n    if (format === undefined) {\n      error = new Error(\n        'Minified exception occurred; use the non-minified dev environment ' +\n          'for the full error message and additional helpful warnings.',\n      );\n    } else {\n      const args = [a, b, c, d, e, f];\n      let argIndex = 0;\n      error = new Error(\n        format.replace(/%s/g, function () {\n          return args[argIndex++];\n        }),\n      );\n      error.name = 'Invariant Violation';\n    }\n\n    error.framesToPop = 1; // we don't care about invariant's own frame\n    throw error;\n  }\n}\n"
  },
  {
    "path": "packages/inferno-router/src/withRouter.ts",
    "content": "import {\n  type Component,\n  type ComponentType,\n  createComponentVNode,\n  type ForwardRef,\n  type InfernoNode,\n  type Ref,\n} from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { Route, type RouteComponentProps } from './Route';\nimport { hoistStaticProperties } from 'inferno-shared';\n\ninterface IWithRouterProps {\n  wrappedComponentRef?: Ref | null;\n}\n\n/**\n * A public higher-order component to access the imperative API\n */\nexport function withRouter<\n  P extends RouteComponentProps<any> & IWithRouterProps,\n>(\n  Com: Function | ComponentType<P> | Component<P, any> | ForwardRef<P, any>,\n): any {\n  const C: any = function (props: RouteComponentProps<any> & IWithRouterProps) {\n    const { wrappedComponentRef, ...remainingProps } = props;\n\n    return createComponentVNode<any>(VNodeFlags.ComponentClass, Route, {\n      render(routeComponentProps: P & IWithRouterProps): InfernoNode {\n        return createComponentVNode(\n          VNodeFlags.ComponentUnknown,\n          Com,\n          { ...remainingProps, ...routeComponentProps },\n          null,\n          wrappedComponentRef,\n        );\n      },\n    });\n  };\n\n  // @ts-expect-error function name property\n  C.displayName = `withRouter(${Com.displayName || Com.name})`;\n  C.WrappedComponent = Com;\n  hoistStaticProperties(C, Com);\n  return C;\n}\n"
  },
  {
    "path": "packages/inferno-server/README.md",
    "content": "# inferno-server\n\n> Inferno package for working with the server\n\nThis package serves as the entry point of the Server-related rendering paths. It is intended to be paired with the isomorphic Inferno, which will be shipped as inferno to npm.\n\n## Install\n\n```\nnpm install inferno inferno-server\n```\n\n## Contents\n\n- renderToString\n- RenderQueueStream\n- RenderStream\n- renderToStaticMarkup\n- renderToString\n- streamAsStaticMarkup\n- streamAsString\n- streamQueueAsStaticMarkup\n- streamQueueAsString\n\n## Usage\n\n```js\nimport { renderToString } from 'inferno-server';\n\nrenderToString(<div>Hello world</div>, container);\n```\n"
  },
  {
    "path": "packages/inferno-server/__tests__/StaticRouter.spec.server-nodom.tsx",
    "content": "import { renderToStaticMarkup } from 'inferno-server';\nimport { Prompt, Redirect, Route, StaticRouter } from 'inferno-router';\n\ndescribe('A <StaticRouter>', () => {\n  it('provides context.router.staticContext in props.staticContext', () => {\n    const ContextChecker = (props, reactContext) => {\n      expect(typeof reactContext.router).toBe('object');\n      expect(reactContext.router.staticContext).toBe(props.staticContext);\n      return null;\n    };\n\n    ContextChecker.contextTypes = {\n      router: () => {},\n    };\n\n    const context = {};\n\n    renderToStaticMarkup(\n      <StaticRouter context={context}>\n        <Route component={ContextChecker} />\n      </StaticRouter>,\n    );\n  });\n\n  it('context.router.staticContext persists inside of a <Route>', () => {\n    const ContextChecker = (_props, reactContext) => {\n      expect(typeof reactContext.router).toBe('object');\n      expect(reactContext.router.staticContext).toBe(context);\n      return null;\n    };\n\n    ContextChecker.contextTypes = {\n      router: () => {},\n    };\n\n    const context = {};\n\n    renderToStaticMarkup(\n      <StaticRouter context={context}>\n        <Route component={ContextChecker} />\n      </StaticRouter>,\n    );\n  });\n\n  it('provides context.router.history', () => {\n    const ContextChecker = (_props, reactContext) => {\n      expect(typeof reactContext.router.history).toBe('object');\n      return null;\n    };\n\n    ContextChecker.contextTypes = {\n      router: () => {},\n    };\n\n    const context = {};\n\n    renderToStaticMarkup(\n      <StaticRouter context={context}>\n        <ContextChecker />\n      </StaticRouter>,\n    );\n  });\n\n  it('warns when passed a history prop', () => {\n    const context = {};\n    const history = {};\n\n    const spy = spyOn(console, 'error');\n\n    renderToStaticMarkup(<StaticRouter context={context} history={history} />);\n\n    expect(spy).toHaveBeenCalledTimes(1);\n    expect(spy.calls.argsFor(0)[0]).toContain(\n      '<StaticRouter> ignores the history prop',\n    );\n    // expect(console.error).toHaveBeenCalledWith(\n    //   expect.stringContaining('<StaticRouter> ignores the history prop')\n    // )\n  });\n\n  it('reports PUSH actions on the context object', () => {\n    const context: Record<string, any> = {};\n\n    renderToStaticMarkup(\n      <StaticRouter context={context}>\n        <Redirect push to=\"/somewhere-else\" />\n      </StaticRouter>,\n    );\n\n    expect(context.action).toBe('PUSH');\n    expect(context.url).toBe('/somewhere-else');\n  });\n\n  it('reports REPLACE actions on the context object', () => {\n    const context: Record<string, any> = {};\n\n    renderToStaticMarkup(\n      <StaticRouter context={context}>\n        <Redirect to=\"/somewhere-else\" />\n      </StaticRouter>,\n    );\n\n    expect(context.action).toBe('REPLACE');\n    expect(context.url).toBe('/somewhere-else');\n  });\n\n  it('knows how to serialize location objects', () => {\n    const context = {};\n\n    renderToStaticMarkup(\n      <StaticRouter context={context}>\n        <Redirect to={{ pathname: '/somewhere-else' }} />\n      </StaticRouter>,\n    );\n\n    // expect(context.action).toBe('REPLACE')\n    // expect(context.location.pathname).toBe('/somewhere-else')\n    // expect(context.location.search).toBeFalsy()\n    // expect(context.location.hash).toBeFalsy()\n    // expect(context.url).toBe('/somewhere-else')\n    expect(context).toEqual({\n      action: 'REPLACE',\n      url: '/somewhere-else',\n      location: {\n        pathname: '/somewhere-else',\n        search: undefined,\n        hash: undefined,\n      },\n    });\n  });\n\n  it('knows how to parse raw URLs', () => {\n    const LocationChecker = (props) => {\n      expect(props.location).toEqual({\n        pathname: '/the/path',\n        search: '?the=query',\n        hash: '#the-hash',\n      });\n      return null;\n    };\n\n    const context = {};\n\n    renderToStaticMarkup(\n      <StaticRouter context={context} location=\"/the/path?the=query#the-hash\">\n        <Route component={LocationChecker} />\n      </StaticRouter>,\n    );\n  });\n\n  describe('with a basename', () => {\n    it('strips the basename from location pathnames', () => {\n      const LocationChecker = (props) => {\n        expect(props.location.pathname).toBe('/path');\n        return null;\n      };\n\n      const context = {};\n\n      renderToStaticMarkup(\n        <StaticRouter\n          context={context}\n          basename=\"/the-base\"\n          location=\"/the-base/path\"\n        >\n          <Route component={LocationChecker} />\n        </StaticRouter>,\n      );\n    });\n\n    it('reports PUSH actions on the context object', () => {\n      const context: Record<string, any> = {};\n\n      renderToStaticMarkup(\n        <StaticRouter context={context} basename=\"/the-base\">\n          <Redirect push to=\"/somewhere-else\" />\n        </StaticRouter>,\n      );\n\n      expect(context.action).toBe('PUSH');\n      expect(context.url).toBe('/the-base/somewhere-else');\n    });\n\n    it('reports REPLACE actions on the context object', () => {\n      const context: Record<string, any> = {};\n\n      renderToStaticMarkup(\n        <StaticRouter context={context} basename=\"/the-base\">\n          <Redirect to=\"/somewhere-else\" />\n        </StaticRouter>,\n      );\n\n      expect(context.action).toBe('REPLACE');\n      expect(context.url).toBe('/the-base/somewhere-else');\n    });\n  });\n\n  describe('no basename', () => {\n    it('createHref does not append extra leading slash', () => {\n      const context: Record<string, any> = {};\n      const pathname = '/test-path-please-ignore';\n\n      interface ILinkProps {\n        to: string;\n        children?: any;\n      }\n\n      const Link = ({ to, children }: ILinkProps) => (\n        <Route\n          children={({ history: { createHref } }) => (\n            <a href={createHref(to)}>{children}</a>\n          )}\n        />\n      );\n\n      const outp = renderToStaticMarkup(\n        <StaticRouter context={context}>\n          <Link to={pathname} />\n        </StaticRouter>,\n      );\n\n      expect(outp).toEqual(`<a href=\"${pathname}\"></a>`);\n    });\n  });\n\n  describe('render a <Prompt>', () => {\n    it('does nothing', () => {\n      const context = {};\n\n      expect(() => {\n        renderToStaticMarkup(\n          <StaticRouter context={context}>\n            <Prompt message=\"this is only a test\" />\n          </StaticRouter>,\n        );\n      }).not.toThrow();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-server/__tests__/animationHooks.spec.server.tsx",
    "content": "import { renderToStaticMarkup, renderToString } from 'inferno-server';\nimport { Component } from 'inferno';\n\n/**\n * NOTE! Animation hooks aren't called during SSR because they use different rendering paths\n */\n\ndescribe('SSR Creation (JSX)', () => {\n  it('should not call \"componentDidAppear\" when component is rendered with renderToStaticMarkup', (done) => {\n    const spyer = jasmine.createSpy();\n    class App extends Component {\n      componentDidAppear(dom) {\n        spyer('didAppear');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const outp = renderToStaticMarkup(<App />);\n\n    // Doing this async to be sure\n    setTimeout(() => {\n      expect(spyer).toHaveBeenCalledTimes(0);\n      expect(outp).toEqual('<div></div>');\n      done();\n    }, 10);\n  });\n\n  it('should not call \"componentDidAppear\" when component is rendered with renderToString', (done) => {\n    const spyer = jasmine.createSpy();\n    class App extends Component {\n      componentDidAppear(dom) {\n        spyer('didAppear');\n        expect(dom instanceof HTMLDivElement).toEqual(true);\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    const outp = renderToString(<App />);\n\n    // Doing this async to be sure\n    setTimeout(() => {\n      expect(spyer).toHaveBeenCalledTimes(0);\n      expect(outp).toEqual('<div></div>');\n      done();\n    }, 10);\n  });\n\n  it('should not call \"onComponentDidAppear\" when component is rendered with renderToStaticMarkup', (done) => {\n    const spyer = jasmine.createSpy();\n\n    const MyComp = () => {\n      return <div />;\n    };\n\n    const onComponentDidAppear = (dom) => {\n      spyer('didAppear');\n      expect(dom instanceof HTMLDivElement).toEqual(true);\n    };\n\n    class App extends Component {\n      render() {\n        return <MyComp onComponentDidAppear={onComponentDidAppear} />;\n      }\n    }\n\n    const outp = renderToStaticMarkup(<App />);\n\n    // Doing this async to be sure\n    setTimeout(() => {\n      expect(spyer).toHaveBeenCalledTimes(0);\n      expect(outp).toEqual('<div></div>');\n      done();\n    }, 10);\n  });\n\n  it('should not call \"onComponentDidAppear\" when component is rendered with renderToString', (done) => {\n    const spyer = jasmine.createSpy();\n\n    const MyComp = () => {\n      return <div />;\n    };\n\n    const onComponentDidAppear = (dom) => {\n      spyer('didAppear');\n      expect(dom instanceof HTMLDivElement).toEqual(true);\n    };\n\n    class App extends Component {\n      render() {\n        return <MyComp onComponentDidAppear={onComponentDidAppear} />;\n      }\n    }\n\n    const outp = renderToString(<App />);\n\n    // Doing this async to be sure\n    setTimeout(() => {\n      expect(spyer).toHaveBeenCalledTimes(0);\n      expect(outp).toEqual('<div></div>');\n      done();\n    }, 10);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-server/__tests__/creation-queuestream.spec.server.tsx",
    "content": "import { Component } from 'inferno';\nimport { streamQueueAsString } from 'inferno-server';\n\nimport concatStream from 'concat-stream';\nimport { createElement } from 'inferno-create-element';\n\nclass StatefulComponent extends Component<{ value: string }> {\n  render() {\n    return createElement('span', null, `stateless ${this.props.value}!`);\n  }\n}\n\nfunction WrappedInput(props) {\n  return <input type=\"text\" value={props.value} />;\n}\n\nclass StatefulPromiseComponent extends Component<{\n  index: number;\n  value?: unknown;\n}> {\n  async getInitialProps() {\n    return await new Promise((resolve) => {\n      // Waits incremenetally for each subindex\n      setTimeout(() => {\n        resolve({\n          value: 'I waited long enough!',\n        });\n      }, 5 * this.props.index);\n    });\n  }\n\n  render() {\n    return createElement(\n      'span',\n      null,\n      `Stateless Item ${this.props.index}: ${this.props.value}`,\n    );\n  }\n}\n\nclass StatefulHierchicalPromiseComponent extends Component<{\n  index: number;\n  value?: unknown;\n}> {\n  async getInitialProps() {\n    return await new Promise((resolve) => {\n      // Waits incremenetally for each subindex\n      setTimeout(() => {\n        resolve({\n          value: `I waited long enough for ${this.props.index}!`,\n        });\n      }, 0);\n    });\n  }\n\n  render() {\n    if (this.props.index > 4) {\n      return createElement(\n        'span',\n        null,\n        `Final Stateless Item ${this.props.index}: ${this.props.value}`,\n      );\n    } else {\n      return createElement(\n        'div',\n        { className: 'child' },\n        `Stateless Item ${this.props.index}: ${this.props.value}`,\n        createElement(StatefulHierchicalPromiseComponent, {\n          index: this.props.index + 1,\n        }),\n      );\n    }\n  }\n}\n\nconst FunctionalComponent = ({ value }) =>\n  createElement('span', null, `stateless ${value}!`);\n\ndescribe('SSR Creation Queue Streams - (non-JSX)', () => {\n  const testEntries = [\n    {\n      description: 'should render div with span child',\n      template: () => createElement('div', null, createElement('span', null)),\n      result: '<div><span></span></div>',\n    },\n    {\n      description: 'should render div with span child and styling',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { style: 'border-left: 10px;' }),\n        ),\n      result: '<div><span style=\"border-left: 10px;\"></span></div>',\n    },\n    // TODO: Fix this\n    // {\n    //   description: \"should render select element with selected property\",\n    //   template: () =>\n    //     createElement('select', {\n    //       value: 'dog'\n    //     }, [\n    //       createElement('option', {value: 'cat'}, 'A cat'),\n    //       createElement('option', {value: 'dog'}, 'A dog')\n    //     ]),\n    //   result: '<select value=\"dog\"><option value=\"cat\">A cat</option><option value=\"dog\" selected>A dog</option></select>'\n    // },\n    {\n      description: 'should render div with span child and styling #2',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { style: { 'border-left': '10px' } }),\n        ),\n      result: '<div><span style=\"border-left:10px;\"></span></div>',\n    },\n    {\n      description: 'should render div with span child and styling #3',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { style: { 'font-family': 'Arial' } }),\n        ),\n      result: '<div><span style=\"font-family:Arial;\"></span></div>',\n    },\n    {\n      description: 'should render div with span child (with className)',\n      template: () =>\n        createElement(\n          'div',\n          { className: 'foo' },\n          createElement('span', { className: 'bar' }),\n        ),\n      result: '<div class=\"foo\"><span class=\"bar\"></span></div>',\n    },\n    {\n      description: 'should render div with text child #1',\n      template: () => createElement('div', null, 'Hello world'),\n      result: '<div>Hello world</div>',\n    },\n    {\n      description: 'should render div with text child (XSS script attack)',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          'Hello world <img src=\"x\" onerror=\"alert(\\'XSS\\')\">',\n        ),\n      result:\n        '<div>Hello world &lt;img src=&quot;x&quot; onerror=&quot;alert(&#039;XSS&#039;)&quot;&gt;</div>',\n    },\n    {\n      description: 'should eascape css style string to prevent XSS injection',\n      template: () =>\n        createElement(\n          'div',\n          {\n            style: ` onmouseover=\"alert(document.domain)\"<script>alert(1)</script>`,\n          },\n        ),\n      result:\n        '<div style=\" onmouseover=&quot;alert(document.domain)&quot;&lt;script&gt;alert(1)&lt;/script&gt;\"></div>',\n    },\n    {\n      description: 'should render div with text children',\n      template: () => createElement('div', null, 'Hello', ' world'),\n      result: '<div>Hello world</div>',\n    },\n    {\n      description: 'should render a void element correct',\n      template: () => createElement('input', null),\n      result: '<input>',\n    },\n    {\n      description: 'should render div with node children',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', null, 'Hello'),\n          createElement('span', null, ' world!'),\n        ),\n      result: '<div><span>Hello</span><span> world!</span></div>',\n    },\n    {\n      description: 'should render div with node children #2',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { id: '123' }, 'Hello'),\n          createElement('span', { className: 'foo' }, ' world!'),\n        ),\n      result:\n        '<div><span id=\"123\">Hello</span><span class=\"foo\"> world!</span></div>',\n    },\n    {\n      description: 'should render div with falsy children',\n      template: () => createElement('div', null, 0),\n      result: '<div>0</div>',\n    },\n    {\n      description: 'should render div with dangerouslySetInnerHTML',\n      template: () =>\n        createElement('div', {\n          dangerouslySetInnerHTML: { __html: '<span>test</span>' },\n        }),\n      result: '<div><span>test</span></div>',\n    },\n    {\n      description: 'should render a stateless component',\n      template: (value) =>\n        createElement(\n          'div',\n          null,\n          createElement(FunctionalComponent, { value }),\n        ),\n      result: '<div><span>stateless foo!</span></div>',\n    },\n    {\n      description: 'should render a div with styles',\n      template: () =>\n        createElement('div', { style: { display: 'block', width: '50px' } }),\n      result: '<div style=\"display:block;width:50px;\"></div>',\n    },\n    {\n      description: 'should ignore null className',\n      template: () => createElement('div', { className: null }),\n      result: '<div></div>',\n    },\n    {\n      description: 'should ignore undefined className',\n      template: () => createElement('div', { className: undefined }),\n      result: '<div></div>',\n    },\n    {\n      description: 'should render a stateful component',\n      template: (value) =>\n        createElement('div', null, createElement(StatefulComponent, { value })),\n      result: '<div><span>stateless foo!</span></div>',\n    },\n    // Following tests check for not only concatenated output, but chunked streams\n    {\n      description: 'should render a stateless component',\n      template: (value) =>\n        createElement(\n          'div',\n          null,\n          createElement(FunctionalComponent, { value }),\n        ),\n      result: [\n        ['<div>', '<span>', 'stateless foo!', '</span>', '</div>'],\n        '<div><span>stateless foo!</span></div>',\n      ],\n    },\n    {\n      description: 'should render a stateful component with promise',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement(StatefulPromiseComponent, { index: 1 }),\n        ),\n      result: [\n        [\n          '<div>',\n          '<span>Stateless Item 1: I waited long enough!</span>',\n          '</div>',\n        ],\n        '<div><span>Stateless Item 1: I waited long enough!</span></div>',\n      ],\n    },\n    {\n      description:\n        'should render a stateful component with promise as hierarchy',\n      template: () =>\n        createElement(StatefulHierchicalPromiseComponent, { index: 1 }),\n      result: [\n        [\n          '<div class=\"child\">Stateless Item 1: I waited long enough for 1!',\n          '<div class=\"child\">Stateless Item 2: I waited long enough for 2!',\n          '<div class=\"child\">Stateless Item 3: I waited long enough for 3!',\n          '<div class=\"child\">Stateless Item 4: I waited long enough for 4!',\n          '<span>Final Stateless Item 5: I waited long enough for 5!</span>',\n          '</div>',\n          '</div>',\n          '</div>',\n          '</div>',\n        ],\n        '<div class=\"child\">Stateless Item 1: I waited long enough for 1!<div class=\"child\">Stateless Item 2: I waited long enough for 2!<div class=\"child\">Stateless Item 3: I waited long enough for 3!<div class=\"child\">Stateless Item 4: I waited long enough for 4!<span>Final Stateless Item 5: I waited long enough for 5!</span></div></div></div></div>',\n      ],\n    },\n    {\n      description: 'should render a stack of stateful component with promise',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement(StatefulPromiseComponent, { index: 1 }),\n          createElement(StatefulPromiseComponent, { index: 2 }),\n          createElement(StatefulPromiseComponent, { index: 3 }),\n        ),\n      result: [\n        [\n          '<div>',\n          '<span>Stateless Item 1: I waited long enough!</span>',\n          '<span>Stateless Item 2: I waited long enough!</span>',\n          '<span>Stateless Item 3: I waited long enough!</span>',\n          '</div>',\n        ],\n        '<div><span>Stateless Item 1: I waited long enough!</span><span>Stateless Item 2: I waited long enough!</span><span>Stateless Item 3: I waited long enough!</span></div>',\n      ],\n    },\n    {\n      description: 'should render opacity style',\n      template: () => createElement('div', { style: { opacity: 0.8 } }),\n      result: '<div style=\"opacity:0.8;\"></div>',\n    },\n    {\n      description: 'Should render div className as number',\n      template: () => createElement('div', { className: 123 }),\n      result: '<div class=\"123\"></div>',\n    },\n    {\n      description: 'Should render input defaultValue as number',\n      template: () => createElement('input', { defaultValue: 123 }),\n      result: '<input value=\"123\">',\n    },\n    // JSX\n    {\n      description: 'should render a null component',\n      template: () => <div>{null}</div>,\n      result: '<div></div>',\n    },\n    {\n      description: 'should render a component with null children',\n      template: () => (\n        <div>\n          {null}\n          <span>emptyValue: {null}</span>\n        </div>\n      ),\n      result: '<div><span>emptyValue: </span></div>',\n    },\n    {\n      description: 'should render a component with valueless attribute',\n      template: () => <script src=\"foo\" async />,\n      result: '<script src=\"foo\" async></script>',\n    },\n    {\n      description: 'should render a stateless component with text',\n      template: () => (\n        <div>\n          Hello world, {'1'}2{'3'}\n        </div>\n      ),\n      result: '<div>Hello world, 123</div>',\n    },\n    {\n      description: 'should render text with escaped symbols',\n      template: () => <div>\"Hello world\"</div>,\n      result: '<div>&quot;Hello world&quot;</div>',\n    },\n    {\n      description: 'should render a stateless component with comments',\n      template: () => <div>Hello world, {/* comment */}</div>,\n      result: '<div>Hello world, </div>',\n    },\n    {\n      description: 'should render mixed invalid/valid children',\n      template: () => <div>{[null, '123', null, '456']}</div>,\n      result: '<div>123456</div>',\n    },\n    {\n      description: 'should ignore children as props',\n      // @ts-expect-error\n      template: () => <p children=\"foo\">foo</p>,\n      result: '<p>foo</p>',\n    },\n    {\n      description: 'should render input with value',\n      template: () => <input value=\"bar\" />,\n      result: '<input value=\"bar\">',\n    },\n    {\n      description:\n        'should render input with value when defaultValue is present',\n      template: () => <input value=\"bar\" defaultValue=\"foo\" />,\n      result: '<input value=\"bar\">',\n    },\n    {\n      description:\n        'should render input when value is not present with defaultValue',\n      template: () => <input defaultValue=\"foo\" />,\n      result: '<input value=\"foo\">',\n    },\n    {\n      description: 'should render input when defaultValue is number',\n      template: () => <input defaultValue={123} />,\n      result: '<input value=\"123\">',\n    },\n    {\n      description:\n        'should render input of type text with value when input is wrapped',\n      template: () => <WrappedInput value=\"foo\" />,\n      result: '<input type=\"text\" value=\"foo\">',\n    },\n    // {\n    //   description: 'should render select element with selected property',\n    //   template: () => (\n    //     <select value=\"dog\">\n    //       <option value=\"cat\">A cat</option>\n    //       <option value=\"dog\">A dog</option>\n    //     </select>\n    //   ),\n    //   result:\n    //     '<select value=\"dog\"><option value=\"cat\">A cat</option><option value=\"dog\" selected>A dog</option></select>'\n    // },\n    {\n      description: 'should render a text placeholder',\n      template: () => (\n        <div>\n          <div>{''}</div>\n          <p>Test</p>\n        </div>\n      ),\n      result: '<div><div> </div><p>Test</p></div>',\n    },\n    {\n      description: 'Should render background color',\n      template: () => (\n        <div\n          style={{ 'background-color': 'red', 'border-bottom-color': 'green' }}\n        />\n      ),\n      result:\n        '<div style=\"background-color:red;border-bottom-color:green;\"></div>',\n    },\n    {\n      description: 'Should not render null styles',\n      template: () => (\n        <div\n          style={{\n            'background-color': null as any,\n            'border-bottom-color': null as any,\n          }}\n        />\n      ),\n      result: '<div></div>',\n    },\n    {\n      description: 'Should style attribute if null',\n      template: () => <div style={null} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'should render div with text child (XSS script attack) #2',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          'Hello world <img src=\"x\" onerror=\"alert(\\'&XSS&\\')\">',\n        ),\n      result:\n        '<div>Hello world &lt;img src=&quot;x&quot; onerror=&quot;alert(&#039;&amp;XSS&amp;&#039;)&quot;&gt;</div>',\n    },\n    {\n      description: 'Should render style opacity #1',\n      template: () => <div style={{ opacity: 0.8 }} />,\n      result: '<div style=\"opacity:0.8;\"></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #1',\n      template: () => <div style={{}} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #2',\n      template: () => <div style={null} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #3',\n      template: () => <div style={false as any} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #4',\n      template: () => <div style={0 as any} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #5',\n      template: () => <div style={true as any} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should render style opacity #2',\n      template: () => <div style=\"opacity:0.8;\" />,\n      result: '<div style=\"opacity:0.8;\"></div>',\n    },\n    {\n      description: 'Should render div className as number',\n      template: () => <div className={123 as any} />,\n      result: '<div class=\"123\"></div>',\n    },\n    {\n      description: 'Should render input defaultValue as number',\n      template: () => <input defaultValue={123} />,\n      result: '<input value=\"123\">',\n    },\n    {\n      description: 'BR should not be closed',\n      template: () => (\n        <div>\n          <br />\n        </div>\n      ),\n      result: '<div><br></div>',\n    },\n    {\n      description: 'You should be able to render an array',\n      template: () => [<p>1</p>, <p>2</p>, <p>3</p>],\n      result: '<p>1</p><p>2</p><p>3</p>',\n    },\n    {\n      description: 'You should be able to render an empty array',\n      template: () => [],\n      result: '<!--!-->',\n    },\n    {\n      description: 'You should be able to render a fragment',\n      template: () => (\n        <>\n          <p>1</p>\n          <p>2</p>\n          <p>3</p>\n        </> /* reset syntax highlighting */\n      ),\n      result: '<p>1</p><p>2</p><p>3</p>',\n    },\n    {\n      description: 'You should be able to render an empty fragment',\n      template: () => <></> /* reset syntax highlighting */,\n      result: '<!--!-->',\n    },\n    {\n      description: 'You should be able to render fragment with single child',\n      template: () => (\n        // @ts-ignore\n        <>\n          <p>1</p>\n        </>\n      ) /* reset syntax highlighting */,\n      result: '<p>1</p>',\n    },\n  ];\n\n  for (const test of testEntries) {\n    it(test.description, async () => {\n      const vDom = test.template('foo');\n\n      return streamPromise(vDom).then((value: string | string[]) => {\n        if (typeof test.result === 'object') {\n          expect(value[0]).toEqual(test.result[0]);\n          expect(value[1]).toBe(test.result[1]);\n        } else {\n          expect(value[1]).toBe(test.result);\n        }\n      });\n    });\n  }\n\n  describe('Component hook', () => {\n    it('Should allow changing state in CWM', async () => {\n      class Another extends Component {\n        constructor(props, context) {\n          super(props, context);\n\n          this.state = {\n            foo: 'bar',\n          };\n        }\n\n        componentWillMount() {\n          this.setState({\n            foo: 'bar2',\n          });\n        }\n\n        render() {\n          return <div>{this.state?.foo}</div>;\n        }\n      }\n\n      class Tester extends Component {\n        constructor(props, context) {\n          super(props, context);\n\n          this.state = {\n            foo: 'bar',\n          };\n        }\n\n        componentWillMount() {\n          this.setState({\n            foo: 'bar2',\n          });\n        }\n\n        render() {\n          return (\n            <div>\n              {this.state?.foo}\n              <Another />\n            </div>\n          );\n        }\n      }\n\n      const vDom = <Tester />;\n      await streamPromise(vDom).then(function (output) {\n        expect(output[1]).toBe('<div>bar2<div>bar2</div></div>');\n      });\n    });\n  });\n\n  describe('misc', () => {\n    it('Should render single text node using state', async () => {\n      class Foobar extends Component {\n        render() {\n          return this.state!.text;\n        }\n\n        componentWillMount() {\n          this.setState({\n            text: 'foo',\n          });\n        }\n      }\n\n      return await streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output[1]).toEqual('<div>foo</div>');\n      });\n    });\n\n    it('Should render single (number) text node using state', async () => {\n      class Foobar extends Component {\n        render() {\n          return this.state!.text;\n        }\n\n        componentWillMount() {\n          this.setState({\n            text: 331,\n          });\n        }\n      }\n\n      return await streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output[1]).toEqual('<div>331</div>');\n      });\n    });\n\n    it('Should render single text node Functional Component', async () => {\n      function Foobar() {\n        return 'foo';\n      }\n\n      return await streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output[1]).toEqual('<div>foo</div>');\n      });\n    });\n\n    it('Should render single (number) text node Functional Component', async () => {\n      function Foobar() {\n        return 0;\n      }\n\n      return await streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output[1]).toEqual('<div>0</div>');\n      });\n    });\n\n    it('Should render checked attribute for input when there is no checked in props', async () => {\n      class Foobar extends Component {\n        render() {\n          // @ts-expect-error\n          // eslint-disable-next-line inferno/no-unknown-property\n          return <input count={1} type=\"checkbox\" defaultChecked={true} />;\n        }\n      }\n\n      return await streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output[1]).toEqual(\n          '<div><input count=\"1\" type=\"checkbox\" checked=\"true\"></div>',\n        );\n      });\n    });\n\n    it('Should render comment when component returns invalid node', async () => {\n      function Foobar() {\n        return null;\n      }\n\n      return await streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output[1]).toEqual('<div><!--!--></div>');\n      });\n    });\n\n    it('Should render single text node Class Component', async () => {\n      class Foobar extends Component {\n        render() {\n          return null;\n        }\n      }\n\n      return await streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output[1]).toEqual('<div><!--!--></div>');\n      });\n    });\n\n    it('Should be possible to use getDerivedStateFromProps', async () => {\n      class Test extends Component {\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            value: 0,\n          };\n        }\n\n        static getDerivedStateFromProps(_props, state) {\n          return {\n            value: state.value + 1,\n          };\n        }\n\n        render() {\n          return <div>{this.state!.value}</div>;\n        }\n      }\n\n      return await streamPromise(<Test />).then(function (output) {\n        expect(output[1]).toEqual('<div>1</div>');\n      });\n    });\n  });\n});\n\nasync function streamPromise(dom) {\n  return await new Promise(function (res: (value: string[]) => void, rej) {\n    const chunks: string[] = [];\n    streamQueueAsString(dom)\n      .on('error', rej)\n      .on('data', (chunk) => {\n        chunks.push(chunk.toString());\n      })\n      .pipe(\n        concatStream(function (buffer) {\n          res([chunks, buffer.toString('utf-8')]);\n        }),\n      );\n  });\n}\n"
  },
  {
    "path": "packages/inferno-server/__tests__/creation-stream.spec.server.ts",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport { streamAsStaticMarkup } from 'inferno-server';\nimport concatStream from 'concat-stream';\n\ndescribe('SSR Root Creation Streams - (non-JSX)', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    document.body.removeChild(container);\n  });\n\n  it('should throw with invalid children', async () => {\n    const test = () => createElement('a', null, true);\n\n    return await streamPromise(test()).catch((err) => {\n      expect(err.toString()).toBe('Error: invalid component');\n    });\n  });\n\n  it('should use getChildContext', async () => {\n    class TestComponent extends Component {\n      getChildContext() {\n        return { hello: 'world' };\n      }\n\n      render() {\n        return createElement('a', null, this.context.hello);\n      }\n    }\n\n    await streamPromise(createElement(TestComponent, null)).then(\n      function (output) {\n        expect(output).toBe('<a>world</a>');\n      },\n    );\n  });\n\n  describe('Component hook', () => {\n    it('Should allow changing state in CWM', async () => {\n      class Another extends Component {\n        constructor(props, context) {\n          super(props, context);\n\n          this.state = {\n            foo: 'bar',\n          };\n        }\n\n        componentWillMount() {\n          this.setState({\n            foo: 'bar2',\n          });\n        }\n\n        render() {\n          return createElement('div', null, this.state!.foo);\n        }\n      }\n\n      class Tester extends Component {\n        constructor(props, context) {\n          super(props, context);\n\n          this.state = {\n            foo: 'bar',\n          };\n        }\n\n        componentWillMount() {\n          this.setState({\n            foo: 'bar2',\n          });\n        }\n\n        render() {\n          return createElement('div', null, [\n            this.state!.foo,\n            createElement(Another),\n          ]);\n        }\n      }\n\n      const vDom = createElement(Tester);\n      await streamPromise(vDom).then(function (output) {\n        expect(output).toBe('<div>bar2<div>bar2</div></div>');\n      });\n    });\n  });\n});\n\nasync function streamPromise(dom) {\n  return await new Promise(function (res, rej) {\n    streamAsStaticMarkup(dom)\n      .on('error', rej)\n      .pipe(\n        concatStream(function (buffer) {\n          res(buffer.toString('utf-8'));\n        }),\n      );\n  });\n}\n"
  },
  {
    "path": "packages/inferno-server/__tests__/creation-stream.spec.server.tsx",
    "content": "import { Component } from 'inferno';\nimport { streamAsString } from 'inferno-server';\nimport concatStream from 'concat-stream';\nimport { createElement } from 'inferno-create-element';\n\nclass StatefulComponent extends Component<{ value: string }> {\n  render() {\n    return createElement('span', null, `stateless ${this.props.value}!`);\n  }\n}\n\nfunction WrappedInput(props) {\n  return <input type=\"text\" value={props.value} />;\n}\n\nconst FunctionalComponent = ({ value }) =>\n  createElement('span', null, `stateless ${value}!`);\n\ndescribe('SSR Creation Streams - (non-JSX)', () => {\n  const testEntries = [\n    {\n      description: 'should render div with span child',\n      template: () => createElement('div', null, createElement('span', null)),\n      result: '<div><span></span></div>',\n    },\n    {\n      description: 'should render div with span child and styling',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { style: 'border-left: 10px;' }),\n        ),\n      result: '<div><span style=\"border-left: 10px;\"></span></div>',\n    },\n    // TODO: Fix this\n    // {\n    //   description: \"should render select element with selected property\",\n    //   template: () =>\n    //     createElement('select', {\n    //       value: 'dog'\n    //     }, [\n    //       createElement('option', {value: 'cat'}, 'A cat'),\n    //       createElement('option', {value: 'dog'}, 'A dog')\n    //     ]),\n    //   result: '<select value=\"dog\"><option value=\"cat\">A cat</option><option value=\"dog\" selected>A dog</option></select>'\n    // },\n    {\n      description: 'should render div with span child and styling #2',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { style: { 'border-left': '10px' } }),\n        ),\n      result: '<div><span style=\"border-left:10px;\"></span></div>',\n    },\n    {\n      description: 'should render div with span child and styling #3',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { style: { 'font-family': 'Arial' } }),\n        ),\n      result: '<div><span style=\"font-family:Arial;\"></span></div>',\n    },\n    {\n      description: 'should render div with span child (with className)',\n      template: () =>\n        createElement(\n          'div',\n          { className: 'foo' },\n          createElement('span', { className: 'bar' }),\n        ),\n      result: '<div class=\"foo\"><span class=\"bar\"></span></div>',\n    },\n    {\n      description: 'should render div with text child #2',\n      template: () => createElement('div', null, 'Hello world'),\n      result: '<div>Hello world</div>',\n    },\n    {\n      description: 'should render div with text child (XSS script attack)',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          'Hello world <img src=\"x\" onerror=\"alert(\\'XSS\\')\">',\n        ),\n      result:\n        '<div>Hello world &lt;img src=&quot;x&quot; onerror=&quot;alert(&#039;XSS&#039;)&quot;&gt;</div>',\n    },\n    {\n      description: 'should eascape css style string to prevent XSS injection',\n      template: () =>\n        createElement(\n          'div',\n          {\n            style: ` onmouseover=\"alert(document.domain)\"<script>alert(1)</script>`,\n          },\n        ),\n      result:\n        '<div style=\" onmouseover=&quot;alert(document.domain)&quot;&lt;script&gt;alert(1)&lt;/script&gt;\"></div>',\n    },\n    {\n      description: 'should render div with text children',\n      template: () => createElement('div', null, 'Hello', ' world'),\n      result: '<div>Hello world</div>',\n    },\n    {\n      description: 'should render a void element correct',\n      template: () => createElement('input', null),\n      result: '<input>',\n    },\n    {\n      description: 'should render div with node children',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', null, 'Hello'),\n          createElement('span', null, ' world!'),\n        ),\n      result: '<div><span>Hello</span><span> world!</span></div>',\n    },\n    {\n      description: 'should render div with node children #2',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { id: '123' }, 'Hello'),\n          createElement('span', { className: 'foo' }, ' world!'),\n        ),\n      result:\n        '<div><span id=\"123\">Hello</span><span class=\"foo\"> world!</span></div>',\n    },\n    {\n      description: 'should render div with falsy children',\n      template: () => createElement('div', null, 0),\n      result: '<div>0</div>',\n    },\n    {\n      description: 'should render div with dangerouslySetInnerHTML',\n      template: () =>\n        createElement('div', {\n          dangerouslySetInnerHTML: { __html: '<span>test</span>' },\n        }),\n      result: '<div><span>test</span></div>',\n    },\n    {\n      description: 'should render a stateful component',\n      template: (value) =>\n        createElement('div', null, createElement(StatefulComponent, { value })),\n      result: '<div><span>stateless foo!</span></div>',\n    },\n    {\n      description: 'should render a stateless component',\n      template: (value) =>\n        createElement(\n          'div',\n          null,\n          createElement(FunctionalComponent, { value }),\n        ),\n      result: '<div><span>stateless foo!</span></div>',\n    },\n    {\n      description: 'should render a stateless component with object props',\n      template: (value) => createElement('a', { [value]: true }),\n      result: '<a foo></a>',\n    },\n    {\n      description: 'should render with array text children',\n      template: () => createElement('a', null, ['a', 'b']),\n      result: '<a>ab</a>',\n    },\n    {\n      description:\n        'should render with array children containing an array of text children',\n      template: () => createElement('a', null, [['a', 'b']]),\n      result: '<a>ab</a>',\n    },\n    {\n      description: 'should render with array null children',\n      template: () => createElement('a', null, ['a', null]),\n      result: '<a>a</a>',\n    },\n    {\n      description: 'should ignore null className',\n      template: () => createElement('div', { className: null }),\n      result: '<div></div>',\n    },\n    {\n      description: 'should ignore undefined className',\n      template: () => createElement('div', { className: undefined }),\n      result: '<div></div>',\n    },\n    {\n      description: 'should render opacity style',\n      template: () => createElement('div', { style: { opacity: 0.8 } }),\n      result: '<div style=\"opacity:0.8;\"></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #1',\n      template: () => <div style={{}} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #2',\n      template: () => <div style={null} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #3',\n      template: () => <div style={false as any} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #4',\n      template: () => <div style={0 as any} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #5',\n      template: () => <div style={true as any} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should render div className as number',\n      template: () => createElement('div', { className: 123 }),\n      result: '<div class=\"123\"></div>',\n    },\n    {\n      description: 'should render a null component',\n      template: () => <div>{null}</div>,\n      result: '<div></div>',\n    },\n    {\n      description: 'should render a component with null children',\n      template: () => (\n        <div>\n          {null}\n          <span>emptyValue: {null}</span>\n        </div>\n      ),\n      result: '<div><span>emptyValue: </span></div>',\n    },\n    {\n      description: 'should render a component with valueless attribute',\n      template: () => <script src=\"foo\" async />,\n      result: '<script src=\"foo\" async></script>',\n    },\n    {\n      description: 'should render a stateless component with text',\n      template: () => (\n        <div>\n          Hello world, {'1'}2{'3'}\n        </div>\n      ),\n      result: '<div>Hello world, 123</div>',\n    },\n    {\n      description: 'should render text with escaped symbols',\n      template: () => <div>\"Hello world\"</div>,\n      result: '<div>&quot;Hello world&quot;</div>',\n    },\n    {\n      description: 'should render a stateless component with comments',\n      template: () => <div>Hello world, {/* comment*/}</div>,\n      result: '<div>Hello world, </div>',\n    },\n    {\n      description: 'should render mixed invalid/valid children',\n      template: () => <div>{[null, '123', null, '456']}</div>,\n      result: '<div>123456</div>',\n    },\n    {\n      description: 'should ignore children as props',\n      // @ts-expect-error\n      template: () => <p children=\"foo\">foo</p>,\n      result: '<p>foo</p>',\n    },\n    {\n      description: 'should render input with value',\n      template: () => <input value=\"bar\" />,\n      result: '<input value=\"bar\">',\n    },\n    {\n      description:\n        'should render input with value when defaultValue is present',\n      template: () => <input value=\"bar\" defaultValue=\"foo\" />,\n      result: '<input value=\"bar\">',\n    },\n    {\n      description:\n        'should render input when value is not present with defaultValue',\n      template: () => <input defaultValue=\"foo\" />,\n      result: '<input value=\"foo\">',\n    },\n    {\n      description: 'should render input when defaultValue is number',\n      template: () => <input defaultValue={123} />,\n      result: '<input value=\"123\">',\n    },\n    {\n      description: 'should render input w/defaultChecked falsy, no checked',\n      template: () => <input type=\"radio\" defaultChecked={false} />,\n      result: '<input type=\"radio\">',\n    },\n    {\n      description: 'should render input w/defaultChecked non-boolean value, no checked',\n      // @ts-expect-error XSS test\n      template: () => <input type=\"radio\" defaultChecked=\"asdasd\" />,\n      result: '<input type=\"radio\">',\n    },\n    {\n      description:\n        'should render input of type text with value when input is wrapped',\n      template: () => <WrappedInput value=\"foo\" />,\n      result: '<input type=\"text\" value=\"foo\">',\n    },\n    // {\n    //   description: 'should render select element with selected property',\n    //   template: () => (\n    //     <select value=\"dog\">\n    //       <option value=\"cat\">A cat</option>\n    //       <option value=\"dog\">A dog</option>\n    //     </select>\n    //   ),\n    //   result:\n    //     '<select value=\"dog\"><option value=\"cat\">A cat</option><option value=\"dog\" selected>A dog</option></select>'\n    // },\n    {\n      description: 'should render a text placeholder',\n      template: () => (\n        <div>\n          <div>{''}</div>\n          <p>Test</p>\n        </div>\n      ),\n      result: '<div><div> </div><p>Test</p></div>',\n    },\n    {\n      description: 'Should render background color',\n      template: () => (\n        <div\n          style={{ 'background-color': 'red', 'border-bottom-color': 'green' }}\n        />\n      ),\n      result:\n        '<div style=\"background-color:red;border-bottom-color:green;\"></div>',\n    },\n    {\n      description: 'Should not render null styles',\n      template: () => (\n        <div\n          style={{\n            'background-color': null as any,\n            'border-bottom-color': null as any,\n          }}\n        />\n      ),\n      result: '<div></div>',\n    },\n    {\n      description: 'Should style attribute if null',\n      template: () => <div style={null} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'should render div with text child (XSS script attack) #2',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          'Hello world <img src=\"x\" onerror=\"alert(\\'&XSS&\\')\">',\n        ),\n      result:\n        '<div>Hello world &lt;img src=&quot;x&quot; onerror=&quot;alert(&#039;&amp;XSS&amp;&#039;)&quot;&gt;</div>',\n    },\n    {\n      description: 'Should render style opacity #1',\n      template: () => <div style={{ opacity: 0.8 }} />,\n      result: '<div style=\"opacity:0.8;\"></div>',\n    },\n    {\n      description: 'Should render style opacity #2',\n      template: () => <div style=\"opacity:0.8;\" />,\n      result: '<div style=\"opacity:0.8;\"></div>',\n    },\n    {\n      description: 'Should render div className as number',\n      template: () => <div className={123 as any} />,\n      result: '<div class=\"123\"></div>',\n    },\n    {\n      description: 'Should render input defaultValue as number',\n      template: () => <input defaultValue={123} />,\n      result: '<input value=\"123\">',\n    },\n    {\n      description: 'BR should not be closed',\n      template: () => (\n        <div>\n          <br />\n        </div>\n      ),\n      result: '<div><br></div>',\n    },\n    {\n      description: 'You should be able to render an array',\n      template: () => [<p>1</p>, <p>2</p>, <p>3</p>],\n      result: '<p>1</p><p>2</p><p>3</p>',\n    },\n    {\n      description: 'You should be able to render an empty array',\n      template: () => [],\n      result: '<!--!-->',\n    },\n    {\n      description: 'You should be able to render a fragment',\n      template: () => (\n        <>\n          <p>1</p>\n          <p>2</p>\n          <p>3</p>\n        </> /* reset syntax highlighting */\n      ),\n      result: '<p>1</p><p>2</p><p>3</p>',\n    },\n    {\n      description: 'You should be able to render an empty fragment',\n      template: () => <></> /* reset syntax highlighting */,\n      result: '<!--!-->',\n    },\n    {\n      description: 'You should be able to render fragment with single child',\n      template: () => (\n        <>\n          <p>1</p>\n        </>\n      ) /* reset syntax highlighting */,\n      result: '<p>1</p>',\n    },\n  ];\n\n  for (const test of testEntries) {\n    it(test.description, () => {\n      const vDom = test.template('foo');\n      return streamPromise(vDom).then(function (output) {\n        expect(output).toBe(test.result);\n      });\n    });\n  }\n\n  describe('Component hook', () => {\n    it('Should allow changing state in CWM', () => {\n      class Another extends Component {\n        public state = {\n          foo: 'bar',\n        };\n\n        constructor(props, context) {\n          super(props, context);\n        }\n\n        componentWillMount() {\n          this.setState({\n            foo: 'bar2',\n          });\n        }\n\n        render() {\n          return <div>{this.state.foo}</div>;\n        }\n      }\n\n      class Tester extends Component {\n        public state = {\n          foo: 'bar',\n        };\n\n        constructor(props, context) {\n          super(props, context);\n        }\n\n        componentWillMount() {\n          this.setState({\n            foo: 'bar2',\n          });\n        }\n\n        render() {\n          return (\n            <div>\n              {this.state.foo}\n              <Another />\n            </div>\n          );\n        }\n      }\n\n      const vDom = <Tester />;\n      return streamPromise(vDom).then(function (output) {\n        expect(output).toBe('<div>bar2<div>bar2</div></div>');\n      });\n    });\n  });\n\n  describe('misc', () => {\n    it('Should render single text node using state', (done) => {\n      interface FoobarState {\n        text: string;\n      }\n\n      class Foobar extends Component<unknown, FoobarState> {\n        render() {\n          return this.state?.text;\n        }\n\n        componentWillMount() {\n          this.setState({\n            text: 'foo',\n          });\n        }\n      }\n\n      streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output).toEqual('<div>foo</div>');\n        done();\n      });\n    });\n\n    it('Should render single (number) text node using state', (done) => {\n      interface FoobarState {\n        text: number;\n      }\n\n      class Foobar extends Component<unknown, FoobarState> {\n        render() {\n          return this.state?.text;\n        }\n\n        componentWillMount() {\n          this.setState({\n            text: 331,\n          });\n        }\n      }\n\n      streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output).toEqual('<div>331</div>');\n        done();\n      });\n    });\n\n    it('Should render single text node Functional Component', (done) => {\n      function Foobar() {\n        return 'foo';\n      }\n\n      streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output).toEqual('<div>foo</div>');\n        done();\n      });\n    });\n\n    it('Should render single (number) text node Functional Component', (done) => {\n      function Foobar() {\n        return 0;\n      }\n\n      streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output).toEqual('<div>0</div>');\n        done();\n      });\n    });\n\n    it('Should render comment when component returns invalid node', (done) => {\n      function Foobar() {\n        return null;\n      }\n\n      streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output).toEqual('<div><!--!--></div>');\n        done();\n      });\n    });\n\n    it('Should render single text node Class Component', (done) => {\n      class Foobar extends Component {\n        render() {\n          return null;\n        }\n      }\n\n      streamPromise(\n        <div>\n          <Foobar />\n        </div>,\n      ).then(function (output) {\n        expect(output).toEqual('<div><!--!--></div>');\n        done();\n      });\n    });\n\n    it('Should be possible to use getDerivedStateFromProps', (done) => {\n      class Test extends Component {\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            value: 0,\n          };\n        }\n\n        static getDerivedStateFromProps(_props, state) {\n          return {\n            value: state.value + 1,\n          };\n        }\n\n        render() {\n          return <div>{this.state!.value}</div>;\n        }\n      }\n\n      streamPromise(<Test />).then(function (output) {\n        expect(output).toEqual('<div>1</div>');\n        done();\n      });\n    });\n  });\n});\n\nfunction streamPromise(dom) {\n  return new Promise(function (res, rej) {\n    streamAsString(dom)\n      .on('error', rej)\n      .pipe(\n        concatStream(function (buffer) {\n          res(buffer.toString('utf-8'));\n        }),\n      );\n  });\n}\n"
  },
  {
    "path": "packages/inferno-server/__tests__/creation.spec.server.ts",
    "content": "import { createElement } from 'inferno-create-element';\nimport { renderToStaticMarkup } from 'inferno-server';\n\n/*\n class StatefulComponent extends Component {\n render() {\n return createElement('span', null, `stateless ${ this.props.value }!`);\n }\n } */\n\nconst FunctionalComponent = ({ value }) =>\n  createElement('span', null, `stateless ${value}!`);\n\ndescribe('SSR Creation (non-JSX)', () => {\n  const testEntries = [\n    {\n      description: 'should render div with span child',\n      template: () => createElement('div', null, createElement('span', null)),\n      result: '<div><span></span></div>',\n    },\n    {\n      description: 'should render div with span child and styling',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { style: 'border-left: 10px;' }),\n        ),\n      result: '<div><span style=\"border-left: 10px;\"></span></div>',\n    },\n    {\n      description: 'should render div with span child and styling #2',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { style: { 'border-left': '10px' } }),\n        ),\n      result: '<div><span style=\"border-left:10px;\"></span></div>',\n    },\n    {\n      description: 'should render div with span child and styling #3',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { style: { 'font-family': 'Arial' } }),\n        ),\n      result: '<div><span style=\"font-family:Arial;\"></span></div>',\n    },\n    {\n      description: 'should render div with span child (with className)',\n      template: () =>\n        createElement(\n          'div',\n          { className: 'foo' },\n          createElement('span', { className: 'bar' }),\n        ),\n      result: '<div class=\"foo\"><span class=\"bar\"></span></div>',\n    },\n    {\n      description: 'should render div with text child',\n      template: () => createElement('div', null, 'Hello world'),\n      result: '<div>Hello world</div>',\n    },\n    {\n      description: 'should render div with text child (XSS script attack)',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          'Hello world <img src=\"x\" onerror=\"alert(\\'XSS\\')\">',\n        ),\n      result:\n        '<div>Hello world &lt;img src=&quot;x&quot; onerror=&quot;alert(&#039;XSS&#039;)&quot;&gt;</div>',\n    },\n    {\n      description: 'should eascape css style string to prevent XSS injection',\n      template: () =>\n        createElement(\n          'div',\n          {\n            style: ` onmouseover=\"alert(document.domain)\"<script>alert(1)</script>`,\n          },\n        ),\n      result:\n        '<div style=\" onmouseover=&quot;alert(document.domain)&quot;&lt;script&gt;alert(1)&lt;/script&gt;\"></div>',\n    },\n    {\n      description: 'should render div with text children',\n      template: () => createElement('div', null, 'Hello', ' world'),\n      result: '<div>Hello world</div>',\n    },\n    {\n      description: 'should render a void element correct',\n      template: () => createElement('input', null),\n      result: '<input>',\n    },\n    {\n      description: 'should render div with node children',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', null, 'Hello'),\n          createElement('span', null, ' world!'),\n        ),\n      result: '<div><span>Hello</span><span> world!</span></div>',\n    },\n    {\n      description: 'should render div with node children #2',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          createElement('span', { id: '123' }, 'Hello'),\n          createElement('span', { className: 'foo' }, ' world!'),\n        ),\n      result:\n        '<div><span id=\"123\">Hello</span><span class=\"foo\"> world!</span></div>',\n    },\n    {\n      description: 'should render div with falsy children',\n      template: () => createElement('div', null, 0),\n      result: '<div>0</div>',\n    },\n    {\n      description: 'should render div with dangerouslySetInnerHTML',\n      template: () =>\n        createElement('div', {\n          dangerouslySetInnerHTML: { __html: '<span>test</span>' },\n        }),\n      result: '<div><span>test</span></div>',\n    },\n    {\n      description: 'should render a stateless component',\n      template: (value) =>\n        createElement(\n          'div',\n          null,\n          createElement(FunctionalComponent, { value }),\n        ),\n      result: '<div><span>stateless foo!</span></div>',\n    },\n    {\n      description: 'should render a div with styles',\n      template: () =>\n        createElement('div', { style: { display: 'block', width: '50px' } }),\n      result: '<div style=\"display:block;width:50px;\"></div>',\n    },\n    {\n      description: 'should ignore null className',\n      template: () => createElement('div', { className: null }),\n      result: '<div></div>',\n    },\n    {\n      description: 'should ignore undefined className',\n      template: () => createElement('div', { className: undefined }),\n      result: '<div></div>',\n    },\n    {\n      description: 'should ignore children as props',\n      template: () => createElement('p', {}, 'foo'),\n      result: '<p>foo</p>',\n    },\n  ];\n\n  for (const test of testEntries) {\n    it(test.description, () => {\n      const vDom = test.template('foo');\n      const output = renderToStaticMarkup(vDom);\n\n      expect(output).toBe(test.result);\n    });\n  }\n});\n"
  },
  {
    "path": "packages/inferno-server/__tests__/creation.spec.server.tsx",
    "content": "import { renderToStaticMarkup, renderToString } from 'inferno-server';\nimport { Component, createFragment } from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport { ChildFlags } from 'inferno-vnode-flags';\nimport { hydrate } from 'inferno-hydrate';\n\nfunction WrappedInput(props: { value: string }) {\n  return <input type=\"text\" value={props.value} />;\n}\n\ndescribe('SSR Creation (JSX)', () => {\n  // @ts-ignore\n  const testEntries = [\n    {\n      description: 'should render a null component',\n      template: () => <div>{null}</div>,\n      result: '<div></div>',\n    },\n    {\n      description: 'should render a component with null children',\n      template: () => (\n        <div>\n          {null}\n          <span>emptyValue: {null}</span>\n        </div>\n      ),\n      result: '<div><span>emptyValue: </span></div>',\n    },\n    {\n      description: 'should render a component with valueless attribute',\n      template: () => <script src=\"foo\" async />,\n      result: '<script src=\"foo\" async></script>',\n    },\n    {\n      description: 'should render a stateless component with text',\n      template: () => (\n        <div>\n          Hello world, {'1'}2{'3'}\n        </div>\n      ),\n      result: '<div>Hello world, 123</div>',\n    },\n    {\n      description: 'should render text with escaped symbols',\n      template: () => <div>\"Hello world\"</div>,\n      result: '<div>&quot;Hello world&quot;</div>',\n    },\n    {\n      description: 'should render a stateless component with comments',\n      template: () => <div>Hello world, {/* comment*/}</div>,\n      result: '<div>Hello world, </div>',\n    },\n    {\n      description: 'should render mixed invalid/valid children',\n      template: () => <div>{[null, '123', null, '456']}</div>,\n      result: '<div>123456</div>',\n    },\n    {\n      description: 'should ignore children as props',\n      // @ts-expect-error\n      template: () => <p children=\"foo\">foo</p>,\n      result: '<p>foo</p>',\n    },\n    {\n      description: 'should render input with value',\n      template: () => <input value=\"bar\" />,\n      result: '<input value=\"bar\">',\n    },\n    {\n      description:\n        'should render input with value when defaultValue is present',\n      template: () => <input value=\"bar\" defaultValue=\"foo\" />,\n      result: '<input value=\"bar\">',\n    },\n    {\n      description:\n        'should render input when value is not present with defaultValue',\n      template: () => <input defaultValue=\"foo\" />,\n      result: '<input value=\"foo\">',\n    },\n    {\n      description: 'should render input when defaultValue is number',\n      template: () => <input defaultValue={123} />,\n      result: '<input value=\"123\">',\n    },\n    {\n      description: 'should render input w/defaultChecked falsy, no checked',\n      template: () => <input type=\"radio\" defaultChecked={false} />,\n      result: '<input type=\"radio\">',\n    },\n    {\n      description: 'should render input w/defaultChecked non-boolean value, no checked',\n      // @ts-expect-error XSS test\n      template: () => <input type=\"radio\" defaultChecked=\"asdasd\" />,\n      result: '<input type=\"radio\">',\n    },\n    {\n      description:\n        'should render input of type text with value when input is wrapped',\n      template: () => <WrappedInput value=\"foo\" />,\n      result: '<input type=\"text\" value=\"foo\">',\n    },\n    {\n      description: 'should render select element with selected property',\n      template: () => (\n        <select value=\"dog\">\n          <option value=\"cat\">A cat</option>\n          <option value=\"dog\">A dog</option>\n        </select>\n      ),\n      result:\n        '<select value=\"dog\"><option value=\"cat\">A cat</option><option value=\"dog\" selected>A dog</option></select>',\n    },\n    {\n      description: 'should render a text placeholder',\n      template: () => (\n        <div>\n          <div>{''}</div>\n          <p>Test</p>\n        </div>\n      ),\n      result: '<div><div> </div><p>Test</p></div>',\n    },\n    {\n      description: 'Should render background color',\n      template: () => (\n        <div\n          style={{ 'background-color': 'red', 'border-bottom-color': 'green' }}\n        />\n      ),\n      result:\n        '<div style=\"background-color:red;border-bottom-color:green;\"></div>',\n    },\n    {\n      description: 'Should not render null styles',\n      template: () => (\n        <div\n          style={{\n            'background-color': null as any,\n            'border-bottom-color': null as any,\n          }}\n        />\n      ),\n      result: '<div></div>',\n    },\n    {\n      description: 'Should style attribute if null',\n      template: () => <div style={null} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'should render div with text child (XSS script attack) #2',\n      template: () =>\n        createElement(\n          'div',\n          null,\n          'Hello world <img src=\"x\" onerror=\"alert(\\'&XSS&\\')\">',\n        ),\n      result:\n        '<div>Hello world &lt;img src=&quot;x&quot; onerror=&quot;alert(&#039;&amp;XSS&amp;&#039;)&quot;&gt;</div>',\n    },\n    {\n      description: 'Should render style opacity #1',\n      template: () => <div style={{ opacity: 0.8 }} />,\n      result: '<div style=\"opacity:0.8;\"></div>',\n    },\n    {\n      description: 'Should render style opacity #2',\n      template: () => <div style=\"opacity:0.8;\" />,\n      result: '<div style=\"opacity:0.8;\"></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #1',\n      template: () => <div style={{}} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #2',\n      template: () => <div style={null} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #3',\n      template: () => <div style={false as any} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #4',\n      template: () => <div style={0 as any} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should not render empty style attribute #5',\n      template: () => <div style={true as any} />,\n      result: '<div></div>',\n    },\n    {\n      description: 'Should render div className as number',\n      template: () => <div className={123 as any} />,\n      result: '<div class=\"123\"></div>',\n    },\n    {\n      description: 'Should render input defaultValue as number',\n      template: () => <input defaultValue={123} />,\n      result: '<input value=\"123\">',\n    },\n    {\n      description: 'BR should not be closed',\n      template: () => (\n        <div>\n          <br />\n        </div>\n      ),\n      result: '<div><br></div>',\n    },\n    {\n      description: 'You should be able to render an array',\n      template: () => [<p>1</p>, <p>2</p>, <p>3</p>],\n      result: '<p>1</p><p>2</p><p>3</p>',\n    },\n    {\n      description: 'You should be able to render an empty array',\n      template: () => [],\n      result: '<!--!-->',\n    },\n    {\n      description: 'You should be able to render a fragment',\n      template: () => (\n        <>\n          <p>1</p>\n          <p>2</p>\n          <p>3</p>\n        </> /* reset syntax highlighting */\n      ),\n      result: '<p>1</p><p>2</p><p>3</p>',\n    },\n    {\n      description: 'You should be able to render an empty fragment',\n      template: () => <></> /* reset syntax highlighting */,\n      result: '<!--!-->',\n    },\n    {\n      description: 'You should be able to render fragment with single child',\n      template: () => (\n        <>\n          <p>1</p>\n        </>\n      ) /* reset syntax highlighting */,\n      result: '<p>1</p>',\n    },\n  ];\n\n  for (const test of testEntries) {\n    it(test.description, () => {\n      const vDom = test.template();\n      const output = renderToStaticMarkup(vDom);\n\n      expect(output).toBe(test.result);\n    });\n  }\n\n  describe('Component hook', () => {\n    it('Should allow changing state in CWM', () => {\n      class Another extends Component {\n        constructor(props, context) {\n          super(props, context);\n\n          this.state = {\n            foo: 'bar',\n          };\n        }\n\n        componentWillMount() {\n          this.setState({\n            foo: 'bar2',\n          });\n        }\n\n        render() {\n          return <div>{this.state!.foo}</div>;\n        }\n      }\n\n      class Tester extends Component {\n        constructor(props, context) {\n          super(props, context);\n\n          this.state = {\n            foo: 'bar',\n          };\n        }\n\n        componentWillMount() {\n          this.setState({\n            foo: 'bar2',\n          });\n        }\n\n        render() {\n          return (\n            <div>\n              {this.state!.foo}\n              <Another />\n            </div>\n          );\n        }\n      }\n\n      const vDom = <Tester />;\n\n      const output = renderToStaticMarkup(vDom);\n\n      expect(output).toBe('<div>bar2<div>bar2</div></div>');\n    });\n  });\n\n  describe('Component string output', () => {\n    it('Should render single text node', () => {\n      class Foobar extends Component {\n        render() {\n          return 'foo';\n        }\n      }\n\n      const output = renderToString(\n        <div>\n          <Foobar />\n        </div>,\n      );\n\n      expect(output).toBe('<div>foo</div>');\n    });\n\n    it('Should render single text node using state', () => {\n      class Foobar extends Component {\n        render() {\n          return this.state!.text;\n        }\n\n        componentWillMount() {\n          this.setState({\n            text: 'foo',\n          });\n        }\n      }\n\n      const output = renderToString(\n        <div>\n          <Foobar />\n        </div>,\n      );\n\n      expect(output).toBe('<div>foo</div>');\n    });\n\n    it('Should render single (number)text node using state', () => {\n      class Foobar extends Component {\n        render() {\n          return this.state!.text;\n        }\n\n        componentWillMount() {\n          this.setState({\n            text: 33,\n          });\n        }\n      }\n\n      const output = renderToString(\n        <div>\n          <Foobar />\n        </div>,\n      );\n\n      expect(output).toBe('<div>33</div>');\n    });\n\n    it('Should render comment when component returns invalid node', () => {\n      function Foobar() {\n        return null;\n      }\n\n      const output = renderToString(\n        <div>\n          <Foobar />\n        </div>,\n      );\n\n      expect(output).toBe('<div><!--!--></div>');\n    });\n\n    it('Should render single text node Class Component', () => {\n      class Foobar extends Component {\n        render() {\n          return null;\n        }\n      }\n\n      const output = renderToString(\n        <div>\n          <Foobar />\n        </div>,\n      );\n\n      expect(output).toBe('<div><!--!--></div>');\n    });\n\n    it('Should render single text node Functional Component', () => {\n      function Foobar() {\n        return 'foo';\n      }\n\n      const output = renderToString(\n        <div>\n          <Foobar />\n        </div>,\n      );\n\n      expect(output).toBe('<div>foo</div>');\n    });\n\n    it('Should render single (number)text node Functional Component', () => {\n      function Foobar() {\n        return 2;\n      }\n\n      const output = renderToString(\n        <div>\n          <Foobar />\n        </div>,\n      );\n\n      expect(output).toBe('<div>2</div>');\n    });\n\n    it('Should render checked attribute for input when there is no checked in props', () => {\n      class Foobar extends Component {\n        render() {\n          // @ts-expect-error\n          // eslint-disable-next-line inferno/no-unknown-property\n          return <input count={1} type=\"checkbox\" defaultChecked={true} />;\n        }\n      }\n\n      const output = renderToString(\n        <div>\n          <Foobar />\n        </div>,\n      );\n\n      expect(output).toBe(\n        '<div><input count=\"1\" type=\"checkbox\" checked=\"true\"></div>',\n      );\n    });\n\n    it('Should throw error if invalid object is sent to renderToString', () => {\n      expect(() => renderToString({ failure: 'guaranteed' })).toThrow();\n      expect(() => renderToString(2)).toThrow();\n    });\n\n    it('Should re-use Css property names from cache when its used multiple times', () => {\n      expect(\n        renderToString(\n          <div style={{ 'background-color': 'red' }}>\n            <div style={{ 'background-color': 'red' }} />\n          </div>,\n        ),\n      ).toEqual(\n        '<div style=\"background-color:red;\"><div style=\"background-color:red;\"></div></div>',\n      );\n    });\n\n    it('text nodes should match 1:1 after hydration', () => {\n      class LinkComponent extends Component {\n        render() {\n          return (\n            <a\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n              href=\"https://github.com/infernojs/create-inferno-app\"\n            >\n              create-inferno-app\n            </a>\n          );\n        }\n      }\n      const container = document.createElement('div');\n      const version = '4.0.0-21';\n      const renderedString = renderToString(\n        <div className=\"built\">\n          Website built with Inferno {version} using <LinkComponent />\n        </div>,\n      );\n      expect(renderedString).toEqual(\n        '<div class=\"built\">Website built with Inferno 4.0.0-21 using <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/infernojs/create-inferno-app\">create-inferno-app</a></div>',\n      );\n\n      container.innerHTML = renderedString;\n\n      const AnchorNode = container.querySelector('a');\n      const wrapperDiv = container.firstChild!;\n\n      function WrapperComponent() {\n        return (\n          <div className=\"built\">\n            Website built with Inferno {version} using <LinkComponent />\n          </div>\n        );\n      }\n\n      hydrate(<WrapperComponent />, container);\n      expect(container.firstChild).toBe(wrapperDiv);\n      expect(wrapperDiv.childNodes.length).toBe(4);\n      expect(wrapperDiv.childNodes[0].nodeValue).toBe(\n        'Website built with Inferno ',\n      );\n      expect(wrapperDiv.childNodes[1].nodeValue).toBe('4.0.0-21');\n      expect(wrapperDiv.childNodes[2].nodeValue).toBe(' using ');\n      expect(wrapperDiv.childNodes[3]).toBe(AnchorNode);\n    });\n\n    it('Should be possible to render Fragment #1', () => {\n      const vNode = (\n        <div>\n          {createFragment(\n            [\n              <div>Lets go!</div>,\n              null,\n              createFragment(\n                [<div>World</div>, 'Of', <em>Fragments</em>],\n                ChildFlags.UnknownChildren,\n              ),\n              'text node',\n            ],\n            ChildFlags.UnknownChildren,\n          )}\n        </div>\n      );\n      const renderedString = renderToString(vNode);\n\n      expect(renderedString).toBe(\n        '<div><div>Lets go!</div><div>World</div>Of<em>Fragments</em>text node</div>',\n      );\n\n      const container = document.createElement('div');\n\n      container.innerHTML = renderedString;\n\n      const emTag = container.querySelector('em');\n\n      hydrate(vNode, container);\n\n      expect(container.innerHTML).toBe(\n        '<div><div>Lets go!</div><div>World</div>Of<em>Fragments</em>text node</div>',\n      );\n      expect(container.querySelector('em')).toBe(emTag);\n    });\n\n    it('Should be possible to render Fragment #2', () => {\n      class Fragmented extends Component {\n        render() {\n          return createFragment(\n            [<div id=\"m\">More</div>, 'Fragments'],\n            ChildFlags.UnknownChildren,\n          );\n        }\n      }\n\n      const vNode = (\n        <div>\n          {createFragment(\n            [\n              <div>Lets go!</div>,\n              <Fragmented />,\n              null,\n              createFragment(\n                [<div>World</div>, 'Of', <em>Fragments</em>],\n                ChildFlags.UnknownChildren,\n              ),\n              'text node',\n              createFragment(\n                [null, 'Go', <em>Code</em>],\n                ChildFlags.UnknownChildren,\n              ),\n            ],\n            ChildFlags.UnknownChildren,\n          )}\n        </div>\n      );\n      const renderedString = renderToString(vNode);\n\n      expect(renderedString).toBe(\n        '<div><div>Lets go!</div><div id=\"m\">More</div>Fragments<div>World</div>Of<em>Fragments</em>text nodeGo<em>Code</em></div>',\n      );\n\n      const container = document.createElement('div');\n\n      container.innerHTML = renderedString;\n\n      const moreDiv = container.querySelector('#m');\n      const emTag = container.querySelector('em');\n\n      hydrate(vNode, container);\n\n      expect(container.innerHTML).toBe(\n        '<div><div>Lets go!</div><div id=\"m\">More</div>Fragments<div>World</div>Of<em>Fragments</em>text nodeGo<em>Code</em></div>',\n      );\n      expect(container.querySelector('em')).toBe(emTag);\n      expect(container.querySelector('#m')).toBe(moreDiv);\n    });\n\n    it('Should be possible to use getDerivedStateFromProps', () => {\n      class Test extends Component {\n        constructor(props) {\n          super(props);\n\n          this.state = {\n            value: 0,\n          };\n        }\n\n        static getDerivedStateFromProps(_props, state) {\n          return {\n            value: state.value + 1,\n          };\n        }\n\n        render() {\n          return <div>{this.state!.value}</div>;\n        }\n      }\n\n      expect(renderToString(<Test />)).toBe('<div>1</div>');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-server/__tests__/hydration-ext.spec.server.tsx",
    "content": "import { Component, createTextVNode, InfernoNode, render } from 'inferno';\nimport { createContainerWithHTML } from 'inferno-utils';\nimport { hydrate } from 'inferno-hydrate';\n\nclass Comp extends Component {\n  render() {\n    return (\n      <div>\n        <div id=\"b1\">block 1</div>\n        <div id=\"b2\">block 2</div>\n        <div id=\"b3\">block 3</div>\n      </div>\n    );\n  }\n}\n\nclass InnerNested extends Component<{ children?: InfernoNode }> {\n  render({ children }) {\n    return children;\n  }\n}\n\nfunction Nested({ children }) {\n  return children;\n}\n\nclass Comp2 extends Component {\n  render() {\n    return (\n      <div>\n        <div id=\"b1\">C 1</div>\n        <div id=\"b2\">C 2</div>\n        <div id=\"b3\">C 3</div>\n      </div>\n    );\n  }\n}\n\nconst compHtml =\n  '<div><div id=\"b1\">block 1</div><div id=\"b2\">block 2</div><div id=\"b3\">block 3</div></div>';\nconst compHtml2 =\n  '<div><div id=\"b1\">C 1</div><div id=\"b2\">C 2</div><div id=\"b3\">C 3</div></div>';\n\ndescribe('SSR Hydration Extended - (JSX)', () => {\n  const tests = [\n    {\n      html: '<div><div>Hello world</div></div>',\n      component: <Comp />,\n    },\n    {\n      html: '<div><div>Hello world</div><div>Hello world</div><div>Hello world</div><div>Hello world</div><div>Hello world</div></div>',\n      component: <Comp />,\n    },\n    {\n      html: '<div><div><div>Hello world</div></div></div>',\n      component: <Comp />,\n    },\n    {\n      html: '<div><div><div>Hello world</div></div><span>Hola</span></div>',\n      component: <Comp />,\n    },\n    {\n      html: '<div><span><div>Hello world</div></span><div><div id=\"b1\">block 1</div><div id=\"b2\">block 2</div><div id=\"b3\">block 3</div></div></div>',\n      component: <Comp />,\n    },\n    {\n      html: '<div><span><div>Hello world</div></span><div><div id=\"b1\">block 1</div><div id=\"b2\">block 2</div><div id=\"b3\">block 3</div></div><span>Hola</span></div>',\n      component: <Comp />,\n    },\n    {\n      html: '<div><div></div></div>',\n      component: (\n        <InnerNested>\n          <Nested>\n            <Comp />\n          </Nested>\n        </InnerNested>\n      ),\n    },\n  ];\n\n  for (let i = 0; i < tests.length; i++) {\n    const { html, component } = [\n      {\n        html: '<div><div>Hello world</div></div>',\n        component: <Comp />,\n      },\n      {\n        html: '<div><div>Hello world</div><div>Hello world</div><div>Hello world</div><div>Hello world</div><div>Hello world</div></div>',\n        component: <Comp />,\n      },\n      {\n        html: '<div><div><div>Hello world</div></div></div>',\n        component: <Comp />,\n      },\n      {\n        html: '<div><div><div>Hello world</div></div><span>Hola</span></div>',\n        component: <Comp />,\n      },\n      {\n        html: '<div><span><div>Hello world</div></span><div><div id=\"b1\">block 1</div><div id=\"b2\">block 2</div><div id=\"b3\">block 3</div></div></div>',\n        component: <Comp />,\n      },\n      {\n        html: '<div><span><div>Hello world</div></span><div><div id=\"b1\">block 1</div><div id=\"b2\">block 2</div><div id=\"b3\">block 3</div></div><span>Hola</span></div>',\n        component: <Comp />,\n      },\n      {\n        html: '<div><div></div></div>',\n        component: (\n          <InnerNested>\n            <Nested>\n              <Comp />\n            </Nested>\n          </InnerNested>\n        ),\n      },\n    ][i];\n    it(`do test #${i + 1}`, () => {\n      const container = createContainerWithHTML(html);\n      hydrate(component, container);\n\n      expect(container.innerHTML).toEqual(compHtml);\n    });\n  }\n\n  it('Should hydrate correctly when CSR children is missing', () => {\n    const container = createContainerWithHTML('<div> </div></div>');\n\n    hydrate(\n      <InnerNested>\n        <Nested>\n          <Comp2 />\n        </Nested>\n      </InnerNested>,\n      container,\n    );\n\n    expect(container.innerHTML).toEqual(compHtml2);\n  });\n\n  it('Should hydrate correctly when CSR component returns null', () => {\n    const container = createContainerWithHTML('<div></div>');\n\n    hydrate(\n      <div>\n        <Nested>\n          <InnerNested />\n        </Nested>\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toEqual('<div></div>');\n  });\n\n  it('Should hydrate correctly when there are comment nodes', () => {\n    const container = createContainerWithHTML('<div></div>');\n\n    hydrate(\n      <div>\n        <Nested>\n          <InnerNested />\n        </Nested>\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toEqual('<div></div>');\n  });\n\n  it('Should hydrate correctly when there are comment nodes #2', () => {\n    const container = createContainerWithHTML('<div></div>');\n\n    hydrate(\n      <div>\n        <Nested>\n          <InnerNested>\n            <p>Hello World!</p>\n          </InnerNested>\n        </Nested>\n      </div>,\n      container,\n    );\n\n    expect(container.innerHTML).toEqual('<div><p>Hello World!</p></div>');\n  });\n\n  it('hasTextChildren - Should handle empty textNodes correctly Github #1137', () => {\n    const container = createContainerWithHTML('<span class=\"error\"></span>');\n\n    const vNode = <span className=\"error\">{''}</span>;\n\n    expect(vNode.children).toEqual('');\n\n    hydrate(vNode, container); // This should create empty text node\n\n    render(<span className=\"error\">{'Okay!'}</span>, container);\n\n    expect(container.textContent).toBe('Okay!');\n  });\n\n  it('hasTextChildren - Should handle empty textNodes correctly Github #1137 variation#2', () => {\n    const container = createContainerWithHTML(\n      '<div><span class=\"error\"></span></div>',\n    );\n\n    const vNode = (\n      <div>\n        <span className=\"error\">{''}</span>\n      </div>\n    );\n\n    expect(vNode.children.children).toEqual('');\n\n    hydrate(vNode, container); // This should create empty text node\n\n    render(\n      <div>\n        <span className=\"error\">{'Okay!'}</span>\n      </div>,\n      container,\n    );\n\n    expect(container.textContent).toBe('Okay!');\n  });\n\n  it('createTextVNode - Should handle empty textNodes correctly Github #1137 variation#3', () => {\n    const container = createContainerWithHTML('<span class=\"error\"></span>');\n\n    const vNode = <span className=\"error\">{createTextVNode('')}</span>;\n\n    hydrate(vNode, container); // This should create empty text node\n\n    expect(container.firstChild?.firstChild).not.toBeNull();\n\n    render(<span className=\"error\">{'Okay!'}</span>, container);\n\n    expect(container.textContent).toBe('Okay!');\n  });\n\n  it('createTextVNode - Should handle empty textNodes correctly Github #1137 variation#4', () => {\n    const container = createContainerWithHTML(\n      '<div><span class=\"error\"></span></div>',\n    );\n\n    const vNode = (\n      <div>\n        <span className=\"error\">{createTextVNode('')}</span>\n      </div>\n    );\n\n    hydrate(vNode, container); // This should create empty text node\n\n    expect(container.firstChild?.firstChild?.firstChild).not.toBeNull();\n\n    render(\n      <div>\n        <span className=\"error\">{'Okay!'}</span>\n      </div>,\n      container,\n    );\n\n    expect(container.textContent).toBe('Okay!');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-server/__tests__/hydration.spec.server.ts",
    "content": "import { render } from 'inferno';\nimport { renderToString } from 'inferno-server';\nimport { hydrate } from 'inferno-hydrate';\nimport { createElement } from 'inferno-create-element';\nimport { createContainerWithHTML, validateNodeTree } from 'inferno-utils';\n\ndescribe('SSR Hydration - (non-JSX)', () => {\n  const node = createElement(\n    'div',\n    null,\n    createElement('span', null, 'Hello world'),\n  );\n  const expect1 = '<div><span>Hello world</span></div>';\n  const expect2 = '<div><span>Hello world</span></div>';\n\n  it('Validate various structures', () => {\n    const html = renderToString(node);\n    const container = createContainerWithHTML(html);\n\n    expect(container.innerHTML).toBe(expect1);\n    hydrate(node, container);\n    expect(validateNodeTree(node)).toBe(true);\n    expect(container.innerHTML).toBe(expect2);\n    render(node, container);\n    expect(container.innerHTML).toBe(expect2);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-server/__tests__/hydration.spec.server.tsx",
    "content": "import { Component, createTextVNode, createVNode, render } from 'inferno';\nimport { renderToString } from 'inferno-server';\nimport { createContainerWithHTML, validateNodeTree } from 'inferno-utils';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport { hydrate } from 'inferno-hydrate';\n\nfunction Comp1() {\n  return <span>Worked!</span>;\n}\n\nfunction Comp2() {\n  return <em>Worked 2!</em>;\n}\n\nclass Comp3 extends Component {\n  render() {\n    return (\n      <em>\n        {['Works', ' ']}\n        <span>again</span>!\n      </em>\n    );\n  }\n}\n\nfunction Comp4({ children }) {\n  return <section>{children}</section>;\n}\n\nclass Comp5 extends Component {\n  render() {\n    return null;\n  }\n}\n\nclass A extends Component {\n  render() {\n    return <span>A</span>;\n  }\n}\n\nclass B extends Component {\n  render() {\n    return <span>B</span>;\n  }\n}\n\ndescribe('SSR Hydration - (JSX)', () => {\n  [\n    {\n      node: (\n        <div>\n          <span>Hello world</span>\n        </div>\n      ),\n      expect1: '<div><span>Hello world</span></div>',\n      expect2: '<div><span>Hello world</span></div>',\n    },\n    {\n      node: (\n        <div>\n          <p>\n            Hello world\n            <sup>\n              <a>Foo</a>\n            </sup>\n          </p>\n        </div>\n      ),\n      expect1: '<div><p>Hello world<sup><a>Foo</a></sup></p></div>',\n      expect2: '<div><p>Hello world<sup><a>Foo</a></sup></p></div>',\n    },\n    {\n      node: <div>{<span>Hello world</span>}</div>,\n      expect1: '<div><span>Hello world</span></div>',\n      expect2: '<div><span>Hello world</span></div>',\n    },\n    {\n      node: (\n        <div>\n          <span>{<span>Hello world</span>}</span>\n        </div>\n      ),\n      expect1: '<div><span><span>Hello world</span></span></div>',\n      expect2: '<div><span><span>Hello world</span></span></div>',\n    },\n    {\n      node: <div>Hello world</div>,\n      expect1: '<div>Hello world</div>',\n      expect2: '<div>Hello world</div>',\n    },\n    {\n      node: (\n        <div>\n          <svg className={(() => 'foo')()} viewBox=\"0 0 64 64\" />\n        </div>\n      ),\n      expect1: '<div><svg class=\"foo\" viewBox=\"0 0 64 64\"></svg></div>',\n      expect2: '<div><svg class=\"foo\" viewBox=\"0 0 64 64\"></svg></div>',\n    },\n    {\n      node: (\n        <Comp4>\n          <h1>Hello world</h1>\n          <p>\n            <em>Foo</em>\n          </p>\n          <p>Woot</p>\n          <p>\n            <em>Bar</em>\n          </p>\n        </Comp4>\n      ),\n      expect1:\n        '<section><h1>Hello world</h1><p><em>Foo</em></p><p>Woot</p><p><em>Bar</em></p></section>',\n      expect2:\n        '<section><h1>Hello world</h1><p><em>Foo</em></p><p>Woot</p><p><em>Bar</em></p></section>',\n    },\n    {\n      node: <div>Hello world, {'Foo!'}</div>,\n      expect1: '<div>Hello world, Foo!</div>',\n      expect2: '<div>Hello world, Foo!</div>',\n    },\n    {\n      node: <div>Hello world, {['Foo!', 'Bar!']}</div>,\n      expect1: '<div>Hello world, Foo!Bar!</div>',\n      expect2: '<div>Hello world, Foo!Bar!</div>',\n    },\n    {\n      node: (\n        <div>\n          Hello world!\n          {null}\n        </div>\n      ),\n      expect1: '<div>Hello world!</div>',\n      expect2: '<div>Hello world!</div>',\n    },\n    {\n      node: (\n        <div>\n          Hello world, {'1'}2{'3'}\n        </div>\n      ),\n      expect1: '<div>Hello world, 123</div>',\n      expect2: '<div>Hello world, 123</div>',\n    },\n    {\n      node: (\n        <div id=\"1\">\n          <div id=\"2\">\n            <div id=\"3\" />\n          </div>\n        </div>\n      ),\n      expect1: '<div id=\"1\"><div id=\"2\"><div id=\"3\"></div></div></div>',\n      expect2: '<div id=\"1\"><div id=\"2\"><div id=\"3\"></div></div></div>',\n    },\n    {\n      node: (\n        <div>\n          <Comp1 />\n        </div>\n      ),\n      expect1: '<div><span>Worked!</span></div>',\n      expect2: '<div><span>Worked!</span></div>',\n    },\n    {\n      node: (\n        <div className=\"test\">\n          <Comp1 />\n        </div>\n      ),\n      expect1: '<div class=\"test\"><span>Worked!</span></div>',\n      expect2: '<div class=\"test\"><span>Worked!</span></div>',\n    },\n    {\n      node: (\n        <div>\n          <Comp1 />\n          <Comp1 />\n          <Comp1 />\n        </div>\n      ),\n      expect1:\n        '<div><span>Worked!</span><span>Worked!</span><span>Worked!</span></div>',\n      expect2:\n        '<div><span>Worked!</span><span>Worked!</span><span>Worked!</span></div>',\n    },\n    {\n      node: (\n        <div>\n          <Comp3 />\n        </div>\n      ),\n      expect1: '<div><em>Works <span>again</span>!</em></div>',\n      expect2: '<div><em>Works <span>again</span>!</em></div>',\n    },\n  ].forEach(({ node, expect1, expect2 }, i) => {\n    it(`Validate various structures #${i + 1}`, () => {\n      const html = renderToString(node);\n      const container = createContainerWithHTML(html);\n\n      expect(container.innerHTML).toBe(expect1);\n      hydrate(node, container);\n      expect(validateNodeTree(node)).toBe(true);\n      expect(container.innerHTML).toBe(expect2);\n      render(node, container);\n      expect(container.innerHTML).toBe(expect2);\n    });\n  });\n\n  [\n    {\n      node: <div>Hello world</div>,\n      expect1: '<div>Hello world</div>',\n      node2: <div>Hello world 2</div>,\n      expect2: '<div>Hello world 2</div>',\n      node3: <div>Hello world</div>,\n      expect3: '<div>Hello world</div>',\n    },\n    {\n      node: <div>Hello world, {'Foo!'}</div>,\n      expect1: '<div>Hello world, Foo!</div>',\n      node2: (\n        <div>\n          {'Start'} Hello world, {'Foo!'}\n        </div>\n      ),\n      expect2: '<div>Start Hello world, Foo!</div>',\n      node3: <div>Hello world, {'Foo!'}</div>,\n      expect3: '<div>Hello world, Foo!</div>',\n    },\n    {\n      node: (\n        <div>\n          Hello world, {'1'}2{'3'}\n        </div>\n      ),\n      expect1: '<div>Hello world, 123</div>',\n      node2: (\n        <div>\n          Hello world, {'3'}2{'1'}\n        </div>\n      ),\n      expect2: '<div>Hello world, 321</div>',\n      node3: (\n        <div>\n          Hello world, {'1'}2{'3'}\n        </div>\n      ),\n      expect3: '<div>Hello world, 123</div>',\n    },\n    {\n      node: (\n        <div id=\"1\">\n          <div id=\"2\">\n            <div id=\"3\" />\n          </div>\n        </div>\n      ),\n      expect1: '<div id=\"1\"><div id=\"2\"><div id=\"3\"></div></div></div>',\n      node2: (\n        <div id=\"3\">\n          <div id=\"2\">\n            <div id=\"1\" />\n          </div>\n        </div>\n      ),\n      expect2: '<div id=\"3\"><div id=\"2\"><div id=\"1\"></div></div></div>',\n      node3: (\n        <div id=\"1\">\n          <div id=\"2\">\n            <div id=\"3\" />\n          </div>\n        </div>\n      ),\n      expect3: '<div id=\"1\"><div id=\"2\"><div id=\"3\"></div></div></div>',\n    },\n    {\n      node: (\n        <div>\n          <Comp1 />\n        </div>\n      ),\n      expect1: '<div><span>Worked!</span></div>',\n      node2: <div />,\n      expect2: '<div></div>',\n      node3: (\n        <div>\n          <Comp1 />\n        </div>\n      ),\n      expect3: '<div><span>Worked!</span></div>',\n    },\n    {\n      node: (\n        <div className=\"test\">\n          <Comp1 />\n        </div>\n      ),\n      expect1: '<div class=\"test\"><span>Worked!</span></div>',\n      node2: (\n        <div className=\"test\">\n          <Comp2 />\n        </div>\n      ),\n      expect2: '<div class=\"test\"><em>Worked 2!</em></div>',\n      node3: (\n        <div className=\"test\">\n          <Comp1 />\n        </div>\n      ),\n      expect3: '<div class=\"test\"><span>Worked!</span></div>',\n    },\n    {\n      node: (\n        <div>\n          <Comp1 />\n          <Comp1 />\n          <Comp1 />\n        </div>\n      ),\n      expect1:\n        '<div><span>Worked!</span><span>Worked!</span><span>Worked!</span></div>',\n      node2: (\n        <div>\n          <Comp2 />\n          <Comp2 />\n          <Comp2 />\n        </div>\n      ),\n      expect2:\n        '<div><em>Worked 2!</em><em>Worked 2!</em><em>Worked 2!</em></div>',\n      node3: (\n        <div>\n          <Comp1 />\n          <Comp1 />\n          <Comp1 />\n        </div>\n      ),\n      expect3:\n        '<div><span>Worked!</span><span>Worked!</span><span>Worked!</span></div>',\n    },\n    {\n      node: (\n        <div>\n          <Comp3 />\n        </div>\n      ),\n      expect1: '<div><em>Works <span>again</span>!</em></div>',\n      node2: (\n        <div>\n          <Comp1 />\n          <Comp3 />\n        </div>\n      ),\n      expect2:\n        '<div><span>Worked!</span><em>Works <span>again</span>!</em></div>',\n      node3: (\n        <div>\n          <Comp3 />\n        </div>\n      ),\n      expect3: '<div><em>Works <span>again</span>!</em></div>',\n    },\n    {\n      node: (\n        <div>\n          <Comp5 />\n        </div>\n      ),\n      expect1: '<div><!--!--></div>',\n      node2: (\n        <div>\n          <Comp5 />\n          <Comp3 />\n          <Comp5 />\n        </div>\n      ),\n      expect2: '<div><em>Works <span>again</span>!</em></div>',\n      node3: (\n        <div>\n          <Comp5 />\n        </div>\n      ),\n      expect3: '<div></div>',\n    },\n  ].forEach(({ node, expect1, node2, node3, expect2, expect3 }, i) => {\n    it(`Update various structures #${i + 1}`, () => {\n      const html = renderToString(node);\n      const container = createContainerWithHTML(html);\n\n      expect(container.innerHTML).toBe(expect1);\n      hydrate(node, container);\n      expect(validateNodeTree(node)).toBe(true);\n      render(node2, container);\n      expect(validateNodeTree(node2)).toBe(true);\n      expect(container.innerHTML).toBe(expect2);\n      render(node3, container);\n      expect(validateNodeTree(node3)).toBe(true);\n      expect(container.innerHTML).toBe(expect3);\n    });\n  });\n\n  it('should rebuild and patch from existing DOM content', () => {\n    const container = document.createElement('div');\n    const vNode = createVNode(\n      VNodeFlags.HtmlElement,\n      'div',\n      'example',\n      createTextVNode('Hello world!'),\n      ChildFlags.HasVNodeChildren,\n    );\n\n    container.innerHTML = '<h1><div>Existing DOM content</div></h1>';\n    hydrate(vNode, container);\n    expect(container.innerHTML).toBe('<div class=\"example\">Hello world!</div>');\n  });\n\n  it('should rebuild and patch from existing DOM content (whitespace) ', () => {\n    const container = document.createElement('div');\n    const vNode = createVNode(\n      VNodeFlags.HtmlElement,\n      'div',\n      'example',\n      createTextVNode('Hello world!'),\n      ChildFlags.HasVNodeChildren,\n    );\n\n    container.appendChild(document.createTextNode(''));\n    container.appendChild(document.createElement('h1'));\n    container.appendChild(document.createTextNode(''));\n    hydrate(vNode, container);\n    expect(container.innerHTML).toBe('<div class=\"example\">Hello world!</div>');\n  });\n\n  it('should rebuild and patch from existing DOM content #2', () => {\n    const container = document.createElement('div');\n    const vNode = createVNode(\n      VNodeFlags.HtmlElement,\n      'div',\n      'example',\n      [\n        createVNode(\n          VNodeFlags.HtmlElement,\n          'div',\n          null,\n          createTextVNode('Item 1'),\n          ChildFlags.HasVNodeChildren,\n        ),\n        createVNode(\n          VNodeFlags.HtmlElement,\n          'div',\n          null,\n          createTextVNode('Item 2'),\n          ChildFlags.HasVNodeChildren,\n        ),\n      ],\n      ChildFlags.HasNonKeyedChildren,\n    );\n\n    container.innerHTML =\n      '<h1><div>Existing DOM content</div><div>Existing DOM content</div><div>Existing DOM content</div></h1><div>Existing DOM content</div>';\n    hydrate(vNode, container);\n    expect(container.innerHTML).toBe(\n      '<div class=\"example\"><div>Item 1</div><div>Item 2</div></div>',\n    );\n  });\n\n  it('should rebuild and patch from existing DOM content #3', () => {\n    const container = document.createElement('div');\n    const vNode = createVNode(\n      VNodeFlags.HtmlElement,\n      'div',\n      'example',\n      [\n        createVNode(\n          VNodeFlags.HtmlElement,\n          'div',\n          null,\n          createTextVNode('Item 1'),\n          ChildFlags.HasVNodeChildren,\n        ),\n        createVNode(\n          VNodeFlags.HtmlElement,\n          'div',\n          null,\n          createTextVNode('Item 2'),\n          ChildFlags.HasVNodeChildren,\n        ),\n      ],\n      ChildFlags.HasNonKeyedChildren,\n    );\n\n    container.innerHTML =\n      '<div><div>Existing DOM content</div><div>Existing DOM content</div><div>Existing DOM content</div></div>';\n    hydrate(vNode, container);\n    expect(container.innerHTML).toBe(\n      '<div class=\"example\"><div>Item 1</div><div>Item 2</div></div>',\n    );\n  });\n\n  it('Should work with setState', () => {\n    class Comp3 extends Component {\n      public readonly state = {\n        i: 0,\n      };\n\n      constructor(props, context) {\n        super(props, context);\n\n        this.clicker = this.clicker.bind(this);\n      }\n\n      componentWillMount() {\n        this.setState({\n          i: this.state.i + 1,\n        });\n      }\n\n      clicker() {\n        this.setState({\n          i: this.state.i + 1,\n        });\n      }\n\n      render() {\n        return (\n          <div>\n            {this.state.i}\n            <span onClick={this.clicker}>1</span>\n          </div>\n        );\n      }\n    }\n\n    const container = document.createElement('div');\n\n    document.body.appendChild(container);\n    container.innerHTML = '<div>1<span>1</span></div>';\n    hydrate(<Comp3 />, container);\n    expect(container.innerHTML).toBe('<div>1<span>1</span></div>');\n\n    container.querySelector('span')!.click();\n\n    expect(container.innerHTML).toBe('<div>2<span>1</span></div>');\n\n    container.querySelector('span')!.click();\n\n    expect(container.innerHTML).toBe('<div>3<span>1</span></div>');\n\n    document.body.removeChild(container);\n  });\n\n  describe('Hydration SSR - CSR mismatches', () => {\n    [\n      {\n        SSR: (\n          <div>\n            <span>Hello world</span>\n          </div>\n        ),\n        SSR_expected: '<div><span>Hello world</span></div>',\n        CSR: (\n          <div>\n            <em>Hello world</em>\n          </div>\n        ),\n        CSR_expected: '<div><em>Hello world</em></div>',\n      },\n      {\n        SSR: (\n          <div>\n            <p>\n              Hello world\n              <sup>\n                <a>Foo</a>\n              </sup>\n            </p>\n          </div>\n        ),\n        SSR_expected: '<div><p>Hello world<sup><a>Foo</a></sup></p></div>',\n        CSR: (\n          <div>\n            <p>\n              Hello bar\n              <span>\n                <em>Foo</em>\n              </span>\n            </p>\n          </div>\n        ),\n        CSR_expected: '<div><p>Hello bar<span><em>Foo</em></span></p></div>',\n      },\n      {\n        SSR: <div>{<span>Hello world</span>}</div>,\n        SSR_expected: '<div><span>Hello world</span></div>',\n        CSR: <em>{<span>Hello 11</span>}</em>,\n        CSR_expected: '<em><span>Hello 11</span></em>',\n      },\n      {\n        SSR: (\n          <div>\n            <span>{<span>Hello world</span>}</span>\n          </div>\n        ),\n        SSR_expected: '<div><span><span>Hello world</span></span></div>',\n        CSR: <em>{<span>Hello 11</span>}</em>,\n        CSR_expected: '<em><span>Hello 11</span></em>',\n      },\n      {\n        SSR: <div>Hello world</div>,\n        SSR_expected: '<div>Hello world</div>',\n        CSR: (\n          <div>\n            <p>\n              Hello bar\n              <span>\n                <em>Foo</em>\n              </span>\n            </p>\n          </div>\n        ),\n        CSR_expected: '<div><p>Hello bar<span><em>Foo</em></span></p></div>',\n      },\n      {\n        SSR: (\n          <div>\n            <svg className={(() => 'foo')()} viewBox=\"0 0 64 64\" />\n          </div>\n        ),\n        SSR_expected: '<div><svg class=\"foo\" viewBox=\"0 0 64 64\"></svg></div>',\n        CSR: (\n          <div>\n            <svg className={(() => 'bar1')()} viewBox=\"0 0 64 11\" />\n          </div>\n        ),\n        CSR_expected: '<div><svg class=\"bar1\" viewBox=\"0 0 64 11\"></svg></div>',\n      },\n      {\n        SSR: (\n          <Comp4>\n            <h1>Hello world</h1>\n            <p>\n              <em>Foo</em>\n            </p>\n            <p>Woot</p>\n            <p>\n              <em>Bar</em>\n            </p>\n          </Comp4>\n        ),\n        SSR_expected:\n          '<section><h1>Hello world</h1><p><em>Foo</em></p><p>Woot</p><p><em>Bar</em></p></section>',\n        CSR: (\n          <Comp4>\n            <h1>Hello world again!</h1>\n            <p>\n              <em>{[1, 2, 3]}</em>\n            </p>\n            <p>{null}</p>\n            <p>\n              <em>Foo</em>\n            </p>\n          </Comp4>\n        ),\n        CSR_expected:\n          '<section><h1>Hello world again!</h1><p><em>123</em></p><p></p><p><em>Foo</em></p></section>',\n      },\n      {\n        SSR: <div>Hello world, {'Foo!'}</div>,\n        SSR_expected: '<div>Hello world, Foo!</div>',\n        CSR: (\n          <Comp4>\n            <h1>Hello world again!</h1>\n            <p>\n              <em>{[1, 2, 3]}</em>\n            </p>\n            <p>{null}</p>\n            <p>\n              <em>Foo</em>\n            </p>\n          </Comp4>\n        ),\n        CSR_expected:\n          '<section><h1>Hello world again!</h1><p><em>123</em></p><p></p><p><em>Foo</em></p></section>',\n      },\n      {\n        SSR: <div>Hello world, {'Foo!'}</div>,\n        SSR_expected: '<div>Hello world, Foo!</div>',\n        CSR: <div>Hello world, {'BarBar!'}</div>,\n        CSR_expected: '<div>Hello world, BarBar!</div>',\n      },\n      {\n        SSR: <div>Hello world, {['Foo!', 'Bar!']}</div>,\n        SSR_expected: '<div>Hello world, Foo!Bar!</div>',\n        CSR: <div>Hello world, {['Foo!', 'Bar!']}</div>,\n        CSR_expected: '<div>Hello world, Foo!Bar!</div>',\n      },\n      {\n        SSR: (\n          <div>\n            Hello world!\n            {null}\n          </div>\n        ),\n        SSR_expected: '<div>Hello world!</div>',\n        CSR: (\n          <div>\n            Hello world!\n            {false}\n          </div>\n        ),\n        CSR_expected: '<div>Hello world!</div>',\n      },\n      {\n        SSR: (\n          <div>\n            Hello world, {'1'}2{'3'}\n          </div>\n        ),\n        SSR_expected: '<div>Hello world, 123</div>',\n        CSR: (\n          <div>\n            Hello world, {'1'}2{[3, 4, 5, [6, 7]]}\n          </div>\n        ),\n        CSR_expected: '<div>Hello world, 1234567</div>',\n      },\n      {\n        SSR: (\n          <div id=\"1\">\n            <div id=\"2\">\n              <div id=\"3\" />\n            </div>\n          </div>\n        ),\n        SSR_expected: '<div id=\"1\"><div id=\"2\"><div id=\"3\"></div></div></div>',\n        CSR: (\n          <div id=\"1\">\n            {[null, false, true, undefined]}\n            <i id=\"2\">\n              <em>1</em>\n              <span id=\"3\" />\n            </i>\n          </div>\n        ),\n        CSR_expected:\n          '<div id=\"1\"><i id=\"2\"><em>1</em><span id=\"3\"></span></i></div>',\n      },\n      {\n        SSR: (\n          <div>\n            <Comp1 />\n          </div>\n        ),\n        SSR_expected: '<div><span>Worked!</span></div>',\n        CSR: (\n          <div id=\"1\">\n            {[null, false, true, undefined]}\n            <i id=\"2\">\n              <em>1</em>\n              <span id=\"3\" />\n            </i>\n          </div>\n        ),\n        CSR_expected:\n          '<div id=\"1\"><i id=\"2\"><em>1</em><span id=\"3\"></span></i></div>',\n      },\n      {\n        SSR: (\n          <div className=\"test\">\n            <Comp1 />\n          </div>\n        ),\n        SSR_expected: '<div class=\"test\"><span>Worked!</span></div>',\n        CSR: (\n          <div>\n            <Comp1 />\n            <Comp1 />\n            <Comp1 />\n          </div>\n        ),\n        CSR_expected:\n          '<div><span>Worked!</span><span>Worked!</span><span>Worked!</span></div>',\n      },\n      {\n        SSR: (\n          <div>\n            <Comp1 />\n            <Comp1 />\n            <Comp1 />\n          </div>\n        ),\n        SSR_expected:\n          '<div><span>Worked!</span><span>Worked!</span><span>Worked!</span></div>',\n        CSR: (\n          <div className=\"test\">\n            <Comp1 />\n          </div>\n        ),\n        CSR_expected: '<div class=\"test\"><span>Worked!</span></div>',\n      },\n      {\n        SSR: <div>foobar</div>,\n        SSR_expected: '<div>foobar</div>',\n        CSR: <A />,\n        CSR_expected: '<span>A</span>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: (\n          <div>\n            <span>Hello world</span>\n          </div>\n        ),\n        SSR_expected: '<div><span>Hello world</span></div>',\n        CSR: (\n          <div>\n            <em>Hello world</em>\n          </div>\n        ),\n        CSR_expected: '<div><em>Hello world</em></div>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: (\n          <div>\n            <p>\n              Hello world\n              <sup>\n                <a>Foo</a>\n              </sup>\n            </p>\n          </div>\n        ),\n        SSR_expected: '<div><p>Hello world<sup><a>Foo</a></sup></p></div>',\n        CSR: (\n          <div>\n            <p>\n              Hello bar\n              <span>\n                <em>Foo</em>\n              </span>\n            </p>\n          </div>\n        ),\n        CSR_expected: '<div><p>Hello bar<span><em>Foo</em></span></p></div>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: <div>{<span>Hello world</span>}</div>,\n        SSR_expected: '<div><span>Hello world</span></div>',\n        CSR: <em>{<span>Hello 11</span>}</em>,\n        CSR_expected: '<em><span>Hello 11</span></em>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: (\n          <div>\n            <span>{<span>Hello world</span>}</span>\n          </div>\n        ),\n        SSR_expected: '<div><span><span>Hello world</span></span></div>',\n        CSR: <em>{<span>Hello 11</span>}</em>,\n        CSR_expected: '<em><span>Hello 11</span></em>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: <div>Hello world</div>,\n        SSR_expected: '<div>Hello world</div>',\n        CSR: (\n          <div>\n            <p>\n              Hello bar\n              <span>\n                <em>Foo</em>\n              </span>\n            </p>\n          </div>\n        ),\n        CSR_expected: '<div><p>Hello bar<span><em>Foo</em></span></p></div>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: (\n          <div>\n            <svg className={(() => 'foo')()} viewBox=\"0 0 64 64\" />\n          </div>\n        ),\n        SSR_expected: '<div><svg class=\"foo\" viewBox=\"0 0 64 64\"></svg></div>',\n        CSR: (\n          <div>\n            <svg className={(() => 'bar1')()} viewBox=\"0 0 64 11\" />\n          </div>\n        ),\n        CSR_expected: '<div><svg class=\"bar1\" viewBox=\"0 0 64 11\"></svg></div>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: (\n          <Comp4>\n            <h1>Hello world</h1>\n            <p>\n              <em>Foo</em>\n            </p>\n            <p>Woot</p>\n            <p>\n              <em>Bar</em>\n            </p>\n          </Comp4>\n        ),\n        SSR_expected:\n          '<section><h1>Hello world</h1><p><em>Foo</em></p><p>Woot</p><p><em>Bar</em></p></section>',\n        CSR: (\n          <Comp4>\n            <h1>Hello world again!</h1>\n            <p>\n              <em>{[1, 2, 3]}</em>\n            </p>\n            <p>{null}</p>\n            <p>\n              <em>Foo</em>\n            </p>\n          </Comp4>\n        ),\n        CSR_expected:\n          '<section><h1>Hello world again!</h1><p><em>123</em></p><p></p><p><em>Foo</em></p></section>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: <div>Hello world, {'Foo!'}</div>,\n        SSR_expected: '<div>Hello world, Foo!</div>',\n        CSR: (\n          <Comp4>\n            <h1>Hello world again!</h1>\n            <p>\n              <em>{[1, 2, 3]}</em>\n            </p>\n            <p>{null}</p>\n            <p>\n              <em>Foo</em>\n            </p>\n          </Comp4>\n        ),\n        CSR_expected:\n          '<section><h1>Hello world again!</h1><p><em>123</em></p><p></p><p><em>Foo</em></p></section>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: <div>Hello world, {'Foo!'}</div>,\n        SSR_expected: '<div>Hello world, Foo!</div>',\n        CSR: <div>Hello world, {'BarBar!'}</div>,\n        CSR_expected: '<div>Hello world, BarBar!</div>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: <div>Hello world, {['Foo!', 'Bar!']}</div>,\n        SSR_expected: '<div>Hello world, Foo!Bar!</div>',\n        CSR: <div>Hello world, {['Foo!', 'Bar!']}</div>,\n        CSR_expected: '<div>Hello world, Foo!Bar!</div>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: (\n          <div>\n            Hello world!\n            {null}\n          </div>\n        ),\n        SSR_expected: '<div>Hello world!</div>',\n        CSR: (\n          <div>\n            Hello world!\n            {false}\n          </div>\n        ),\n        CSR_expected: '<div>Hello world!</div>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: (\n          <div>\n            Hello world, {'1'}2{'3'}\n          </div>\n        ),\n        SSR_expected: '<div>Hello world, 123</div>',\n        CSR: (\n          <div>\n            Hello world, {'1'}2{[3, 4, 5, [6, 7]]}\n          </div>\n        ),\n        CSR_expected: '<div>Hello world, 1234567</div>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: (\n          <div id=\"1\">\n            <div id=\"2\">\n              <div id=\"3\" />\n            </div>\n          </div>\n        ),\n        SSR_expected: '<div id=\"1\"><div id=\"2\"><div id=\"3\"></div></div></div>',\n        CSR: (\n          <div id=\"1\">\n            {[null, false, true, undefined]}\n            <i id=\"2\">\n              <em>1</em>\n              <span id=\"3\" />\n            </i>\n          </div>\n        ),\n        CSR_expected:\n          '<div id=\"1\"><i id=\"2\"><em>1</em><span id=\"3\"></span></i></div>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: (\n          <div>\n            <Comp1 />\n          </div>\n        ),\n        SSR_expected: '<div><span>Worked!</span></div>',\n        CSR: (\n          <div id=\"1\">\n            {[null, false, true, undefined]}\n            <i id=\"2\">\n              <em>1</em>\n              <span id=\"3\" />\n            </i>\n          </div>\n        ),\n        CSR_expected:\n          '<div id=\"1\"><i id=\"2\"><em>1</em><span id=\"3\"></span></i></div>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: (\n          <div className=\"test\">\n            <Comp1 />\n          </div>\n        ),\n        SSR_expected: '<div class=\"test\"><span>Worked!</span></div>',\n        CSR: (\n          <div>\n            <Comp1 />\n            <Comp1 />\n            <Comp1 />\n          </div>\n        ),\n        CSR_expected:\n          '<div><span>Worked!</span><span>Worked!</span><span>Worked!</span></div>',\n        CSR2: <B />,\n        CSR2_expected: '<span>B</span>',\n      },\n      {\n        SSR: (\n          <div>\n            <Comp1 />\n            <Comp1 />\n            <Comp1 />\n          </div>\n        ),\n        SSR_expected:\n          '<div><span>Worked!</span><span>Worked!</span><span>Worked!</span></div>',\n        CSR: (\n          <div className=\"test\">\n            <Comp1 />\n          </div>\n        ),\n        CSR_expected: '<div class=\"test\"><span>Worked!</span></div>',\n        CSR2: (\n          <div>\n            <B />\n          </div>\n        ),\n        CSR2_expected: '<div><span>B</span></div>',\n      },\n    ].forEach(\n      ({ SSR, CSR, CSR2, SSR_expected, CSR_expected, CSR2_expected }, i) => {\n        it(`Validate various structures #${i + 1}`, () => {\n          const ssrString = renderToString(SSR);\n          const SsrContainer = createContainerWithHTML(ssrString);\n\n          expect(SsrContainer.innerHTML).toBe(SSR_expected);\n          hydrate(CSR, SsrContainer);\n\n          if (CSR2) {\n            // Do some repeating here to verify vNodes are correctly set\n            render(CSR2, SsrContainer); // patch 2\n            expect(SsrContainer.innerHTML).toBe(CSR2_expected);\n            render(CSR2, SsrContainer); // patch 2\n            expect(SsrContainer.innerHTML).toBe(CSR2_expected);\n            render(CSR, SsrContainer); // patch 1\n            expect(SsrContainer.innerHTML).toBe(CSR_expected);\n            render(CSR2, SsrContainer); // patch 2\n            expect(SsrContainer.innerHTML).toBe(CSR2_expected);\n          } else {\n            expect(SsrContainer.innerHTML).toBe(CSR_expected);\n            render(CSR, SsrContainer); // patch 1\n            expect(SsrContainer.innerHTML).toBe(CSR_expected);\n          }\n        });\n      },\n    );\n  });\n});\n"
  },
  {
    "path": "packages/inferno-server/__tests__/loaderOnRoute.spec.server.tsx",
    "content": "import { render } from 'inferno';\nimport { renderToString } from 'inferno-server';\nimport {\n  BrowserRouter,\n  StaticRouter,\n  Route,\n  useLoaderData,\n  resolveLoaders,\n  traverseLoaders,\n} from 'inferno-router';\n\ndescribe('Resolve loaders during server side rendering', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n    // Reset history to root\n    history.replaceState(undefined, '', '/');\n  });\n\n  it('SSR renders same result as browser', async () => {\n    const TEXT = 'bubblegum';\n    const Component = (props) => {\n      const res = useLoaderData(props);\n      return <h1>{res?.message}</h1>;\n    };\n\n    const loaderFuncNoHit = async () => {\n      return { message: 'no' };\n    };\n    const loaderFunc = async () => {\n      return { message: TEXT };\n    };\n\n    const routes = [\n      <Route path=\"/flowers\" render={Component} loader={loaderFuncNoHit} />,\n      <Route path=\"/birds\" render={Component} loader={loaderFunc} />,\n      <Route path=\"/bees\" render={Component} loader={loaderFuncNoHit} />,\n    ];\n\n    const loaderEntries = traverseLoaders('/birds', routes);\n    const initialData = await resolveLoaders(loaderEntries);\n\n    // Render on server\n    const html = renderToString(\n      <StaticRouter context={{}} location=\"/birds\" initialData={initialData}>\n        {routes}\n      </StaticRouter>,\n    );\n\n    // Render in browser\n    history.replaceState(undefined, '', '/birds');\n    render(\n      <BrowserRouter initialData={initialData}>{routes}</BrowserRouter>,\n      container,\n    );\n\n    expect(`<!--!-->${container.innerHTML}<!--!-->`).toEqual(html);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-server/__tests__/observer.spec.server.tsx",
    "content": "import { render } from 'inferno';\nimport { observer, useStaticRendering } from 'inferno-mobx';\nimport { renderToStaticMarkup } from 'inferno-server';\nimport { getObserverTree, observable } from 'mobx';\n\ndescribe('Mobx Observer Server', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  it('does not views alive when using static + string rendering', function () {\n    useStaticRendering(true);\n\n    let renderCount = 0;\n    const data = observable({\n      z: 'hi',\n    });\n\n    const TestComponent = observer(function testComponent() {\n      renderCount++;\n      return <div>{data.z}</div>;\n    });\n\n    const output = renderToStaticMarkup(<TestComponent />);\n\n    data.z = 'hello';\n\n    expect(output).toBe('<div>hi</div>');\n    expect(renderCount).toBe(1);\n\n    expect(getObserverTree(data, 'z').observers).not.toBeDefined();\n\n    useStaticRendering(false);\n  });\n});\n"
  },
  {
    "path": "packages/inferno-server/__tests__/props-context.spec.server.tsx",
    "content": "import { renderToStaticMarkup } from 'inferno-server';\nimport { Component, InfernoNode } from 'inferno';\n\ndescribe('SSR render() arguments', () => {\n  class TestProvider extends Component<{ children?: InfernoNode }> {\n    getChildContext() {\n      return { testContext: 'context-works' };\n    }\n\n    render({ children }) {\n      return children;\n    }\n  }\n\n  it('should have props as 1st argument', () => {\n    interface TestChildProps {\n      testProps: string;\n    }\n\n    class TestChild extends Component<TestChildProps> {\n      render(props) {\n        return <p>{props.testProps}</p>;\n      }\n    }\n\n    const output = renderToStaticMarkup(<TestChild testProps=\"props-works\" />);\n    expect(output).toBe('<p>props-works</p>');\n  });\n\n  it('should have state as 2nd argument', () => {\n    class TestChild extends Component {\n      constructor() {\n        super();\n        this.state = { testState: 'state-works' };\n      }\n\n      render(_props, state) {\n        return <p>{state.testState}</p>;\n      }\n    }\n    const output = renderToStaticMarkup(<TestChild />);\n    expect(output).toBe('<p>state-works</p>');\n  });\n\n  it('statefull has context as 3rd argument', () => {\n    class TestChild extends Component {\n      render(_props, _state, context) {\n        return <p>{context.testContext}</p>;\n      }\n    }\n\n    const output = renderToStaticMarkup(\n      <TestProvider>\n        <TestChild />\n      </TestProvider>,\n    );\n    expect(output).toBe('<p>context-works</p>');\n  });\n\n  it('stateless has context as 2nd argument', () => {\n    function TestChild(_props, context) {\n      return <p>{context.testContext}</p>;\n    }\n\n    const output = renderToStaticMarkup(\n      <TestProvider>\n        <TestChild />\n      </TestProvider>,\n    );\n    expect(output).toBe('<p>context-works</p>');\n  });\n\n  it('nested stateless has context as 2nd argument', () => {\n    function ChildWrapper(props) {\n      return props.children;\n    }\n    function TestChild(_props, context) {\n      return <p>{context.testContext}</p>;\n    }\n    const output = renderToStaticMarkup(\n      <TestProvider>\n        <ChildWrapper>\n          <ChildWrapper>\n            <TestChild />\n          </ChildWrapper>\n        </ChildWrapper>\n      </TestProvider>,\n    );\n    expect(output).toBe('<p>context-works</p>');\n  });\n\n  it('nested providers should have merged context', () => {\n    class TestContext extends Component<{ children?: InfernoNode }> {\n      getChildContext() {\n        return { testContextWrap: 'context-wrap-works' };\n      }\n\n      render({ children }) {\n        return children;\n      }\n    }\n    function TestChild(_props: unknown, context) {\n      return (\n        <p>\n          {context.testContext}|{context.testContextWrap}\n        </p>\n      );\n    }\n    const output = renderToStaticMarkup(\n      <TestProvider>\n        <TestContext>\n          <TestChild />\n        </TestContext>\n      </TestProvider>,\n    );\n    expect(output).toBe('<p>context-works|context-wrap-works</p>');\n  });\n});\n"
  },
  {
    "path": "packages/inferno-server/__tests__/security.spec.server.tsx",
    "content": "import { createElement } from 'inferno-create-element';\nimport {\n  renderToString,\n  streamAsString,\n  streamQueueAsString,\n} from 'inferno-server';\nimport concatStream from 'concat-stream';\n\ndescribe('Security - SSR', () => {\n  describe('renderToString', () => {\n    it('Should not render invalid tagNames', () => {\n      expect(() => renderToString(createElement('div'))).not.toThrow();\n      expect(() => renderToString(createElement('x-💩'))).not.toThrow();\n      expect(() => renderToString(createElement('a b'))).toThrow(/<a b>/);\n      expect(() => renderToString(createElement('a\\0b'))).toThrow(/<a\\0b>/);\n      expect(() => renderToString(createElement('a>'))).toThrow(/<a>>/);\n      expect(() => renderToString(createElement('<'))).toThrow(/<<>/);\n      expect(() => renderToString(createElement('\"'))).toThrow(/<\">/);\n    });\n\n    it('Should not render invalid attribute names', () => {\n      const props = {};\n      const userProvidedData = '></div><script>alert(\"hi\")</script>';\n\n      props[userProvidedData] = 'hello';\n\n      const html = renderToString(<div {...props} />);\n\n      expect(html).toBe('<div></div>');\n    });\n\n    it('should reject attribute key injection attack on markup', () => {\n      const element1 = createElement(\n        'div',\n        { 'blah\" onclick=\"beevil\" noise=\"hi': 'selected' },\n        null,\n      );\n      const element2 = createElement(\n        'div',\n        { '></div><script>alert(\"hi\")</script>': 'selected' },\n        null,\n      );\n      const result1 = renderToString(element1);\n      const result2 = renderToString(element2);\n      expect(result1.toLowerCase()).not.toContain('onclick');\n      expect(result2.toLowerCase()).not.toContain('script');\n    });\n  });\n\n  describe('streams', () => {\n    for (const method of [streamAsString, streamQueueAsString]) {\n      it('Should not render invalid attribute names', () => {\n        const props = {};\n        const userProvidedData = '></div><script>alert(\"hi\")</script>';\n\n        props[userProvidedData] = 'hello';\n\n        streamPromise(<div {...props} />, method).then((html) => {\n          expect(html).toBe('<div></div>');\n        });\n      });\n\n      it('should reject attribute key injection attack on markup', (done) => {\n        const element1 = createElement(\n          'div',\n          { 'blah\" onclick=\"beevil\" noise=\"hi': 'selected' },\n          null,\n        );\n        streamPromise(element1, method).then((result1) => {\n          expect(result1.toLowerCase()).not.toContain('onclick');\n          done();\n        });\n      });\n\n      it('should reject attribute key injection attack on markup #2', (done) => {\n        const element2 = createElement(\n          'div',\n          { '></div><script>alert(\"hi\")</script>': 'selected' },\n          null,\n        );\n        streamPromise(element2, method).then((result2) => {\n          expect(result2.toLowerCase()).not.toContain('script');\n          done();\n        });\n      });\n    }\n  });\n});\n\nasync function streamPromise(dom, method) {\n  return await new Promise(function (res: (value: string) => void, rej) {\n    method(dom)\n      .on('error', rej)\n      .pipe(\n        concatStream(function (buffer) {\n          res(buffer.toString('utf-8'));\n        }),\n      );\n  });\n}\n"
  },
  {
    "path": "packages/inferno-server/__tests__/ssr-forwardref.spec.tsx",
    "content": "import {\n  Component,\n  createRef,\n  forwardRef,\n  type RefObject,\n  render,\n} from 'inferno';\nimport {\n  renderToString,\n  streamAsString,\n  streamQueueAsString,\n} from 'inferno-server';\nimport { hydrate } from 'inferno-hydrate';\nimport { isString } from 'inferno-shared';\nimport concatStream from 'concat-stream';\n\ndescribe('SSR -> Hydrate - Forward Ref', () => {\n  let container;\n\n  beforeEach(function () {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(function () {\n    render(null, container);\n    container.innerHTML = '';\n    document.body.removeChild(container);\n  });\n\n  function SSRtoString(method, vNode, callback) {\n    const val = method(vNode);\n\n    if (isString(val)) {\n      callback(val);\n    } else {\n      val.pipe(\n        concatStream(function (buffer) {\n          callback(buffer.toString('utf-8'));\n        }),\n      );\n    }\n  }\n\n  for (const method of [renderToString, streamAsString, streamQueueAsString]) {\n    it('Should be possible to forward createRef', (done) => {\n      const FancyButton = forwardRef((props, ref) => (\n        <button ref={ref} className=\"FancyButton\">\n          {props.children}\n        </button>\n      ));\n\n      expect(FancyButton.render).toBeDefined();\n\n      class Hello extends Component<any, any> {\n        private readonly btn: RefObject<any>;\n\n        constructor(props) {\n          super(props);\n\n          // You can now get a ref directly to the DOM button:\n          this.btn = createRef();\n        }\n\n        public componentDidMount() {\n          expect(this.btn.current).toBe(container.querySelector('button'));\n        }\n\n        public render() {\n          return <FancyButton ref={this.btn}>Click me!</FancyButton>;\n        }\n      }\n\n      SSRtoString(method, <Hello />, function (htmlString) {\n        expect(htmlString).toBe(\n          '<button class=\"FancyButton\">Click me!</button>',\n        );\n\n        container.innerHTML = htmlString;\n\n        renderToString(<Hello />);\n\n        expect(container.innerHTML).toBe(\n          '<button class=\"FancyButton\">Click me!</button>',\n        );\n\n        hydrate(<Hello />, container);\n\n        expect(container.innerHTML).toBe(\n          '<button class=\"FancyButton\">Click me!</button>',\n        );\n\n        done();\n      });\n    });\n\n    it('Should be possible to forward callback ref', (done) => {\n      const FancyButton = forwardRef((props, ref) => (\n        <button ref={ref} className=\"FancyButton\">\n          {props.children}\n        </button>\n      ));\n\n      expect(FancyButton.render).toBeDefined();\n\n      class Hello extends Component {\n        public render() {\n          return (\n            <FancyButton\n              ref={(btn) => {\n                if (btn) {\n                  expect(btn).toBe(container.querySelector('button'));\n                }\n              }}\n            >\n              Click me!\n            </FancyButton>\n          );\n        }\n      }\n\n      SSRtoString(method, <Hello />, function (htmlString) {\n        container.innerHTML = htmlString;\n\n        expect(container.innerHTML).toBe(\n          '<button class=\"FancyButton\">Click me!</button>',\n        );\n\n        hydrate(<Hello />, container);\n\n        expect(container.innerHTML).toBe(\n          '<button class=\"FancyButton\">Click me!</button>',\n        );\n\n        render(null, container);\n\n        expect(container.innerHTML).toBe('');\n\n        done();\n      });\n    });\n\n    it('Should be possible to patch forwardRef component', () => {\n      const FancyButton = forwardRef((props, ref) => {\n        return (\n          <button ref={ref} className=\"FancyButton\">\n            {props.children}\n          </button>\n        );\n      });\n\n      expect(FancyButton.render).toBeDefined();\n\n      SSRtoString(method, <FancyButton />, function (htmlString) {\n        let firstVal: Element | null = null;\n\n        container.innerHTML = htmlString;\n\n        hydrate(\n          <FancyButton\n            ref={(btn) => {\n              firstVal = btn;\n            }}\n          >\n            Click me!\n          </FancyButton>,\n          container,\n        );\n\n        expect(container.innerHTML).toBe(\n          '<button class=\"FancyButton\">Click me!</button>',\n        );\n        expect(firstVal).not.toBe(null);\n\n        let secondVal: Element | null = null;\n\n        render(\n          <FancyButton\n            ref={(btn) => {\n              secondVal = btn;\n            }}\n          >\n            Click me! 222\n          </FancyButton>,\n          container,\n        );\n\n        expect(firstVal).toBe(null);\n        expect(secondVal).not.toBe(null);\n\n        expect(container.innerHTML).toBe(\n          '<button class=\"FancyButton\">Click me! 222</button>',\n        );\n      });\n    });\n  }\n});\n"
  },
  {
    "path": "packages/inferno-server/__tests__/utils.spec.server.tsx",
    "content": "import { render } from 'inferno';\nimport { renderToString } from 'inferno-server';\nimport { createContainerWithHTML, validateNodeTree } from 'inferno-utils';\n\ndescribe('Utils - SSR', () => {\n  describe('validateNodeTree', () => {\n    it('should return true on a valid node tree', () => {\n      const node = (\n        <div>\n          <span>Hello world</span>\n        </div>\n      );\n      const html = renderToString(node);\n      const container = createContainerWithHTML(html);\n      render(node, container);\n      expect(validateNodeTree(node)).toBe(true);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-server/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-server/index.mjs",
    "content": "export * from './dist/index.mjs';\n\nif (process.env.NODE_ENV !== 'production') {\n  console.warn(\n    'You are running production build of Inferno-server in development mode. Use dev:module entry point.',\n  );\n}\n"
  },
  {
    "path": "packages/inferno-server/package.json",
    "content": "{\n  \"name\": \"inferno-server\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Provides methods to render HTML strings from Inferno elements\",\n  \"author\": {\n    \"name\": \"Dominic Gannaway\",\n    \"email\": \"dg@domgan.com\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"keywords\": [\n    \"babel\",\n    \"react\",\n    \"inferno\",\n    \"framework\",\n    \"interfaces\",\n    \"user interfaces\",\n    \"html\",\n    \"renderToString\",\n    \"server\",\n    \"dom\",\n    \"browser\",\n    \"rollup\"\n  ],\n  \"files\": [\n    \"index.cjs\",\n    \"index.mjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-server\"\n  },\n  \"engines\": {\n    \"node\": \">=8\"\n  },\n  \"devDependencies\": {\n    \"inferno-create-element\": \"9.0.11\",\n    \"inferno-hydrate\": \"9.0.11\",\n    \"inferno-shared\": \"9.0.11\",\n    \"inferno-vnode-flags\": \"9.0.11\",\n    \"mobx\": \"*\"\n  },\n  \"dependencies\": {\n    \"inferno\": \"9.0.11\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\",\n      \"inferno-vnode-flags\"\n    ],\n    \"moduleName\": \"Inferno.Server\",\n    \"moduleGlobals\": {\n      \"inferno\": \"Inferno\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/inferno-server/src/index.ts",
    "content": "import { renderToString } from './renderToString';\nimport {\n  RenderQueueStream,\n  streamQueueAsString,\n} from './renderToString.queuestream';\nimport { RenderStream, streamAsString } from './renderToString.stream';\n\n// Inferno does not generate \"data-root\" attributes so staticMarkup is literally same as renderToString\nexport {\n  RenderQueueStream,\n  RenderStream,\n  renderToString as renderToStaticMarkup,\n  renderToString,\n  streamAsString as streamAsStaticMarkup,\n  streamAsString,\n  streamQueueAsString as streamQueueAsStaticMarkup,\n  streamQueueAsString,\n};\n"
  },
  {
    "path": "packages/inferno-server/src/prop-renderers.ts",
    "content": "import { isString, isStringOrNumber } from 'inferno-shared';\nimport { escapeText } from \"./utils\";\n\nfunction parseStyleAsString(styles: string | object): string {\n  if (isString(styles)) {\n    return escapeText(styles);\n  } else {\n    let renderedString = '';\n    for (const styleName in styles) {\n      const value = styles[styleName];\n\n      if (isStringOrNumber(value)) {\n        renderedString += `${styleName}:${value};`;\n      }\n    }\n    return renderedString;\n  }\n}\n\nexport function renderStyleAttribute(styles: string | object): string {\n  const stylesString = parseStyleAsString(styles);\n\n  if (stylesString) {\n    return ` style=\"${stylesString}\"`;\n  }\n\n  return '';\n}\n"
  },
  {
    "path": "packages/inferno-server/src/renderToString.queuestream.ts",
    "content": "import { EMPTY_OBJ } from 'inferno';\nimport {\n  isArray,\n  isFunction,\n  isInvalid,\n  isNull,\n  isNullOrUndef,\n  isNumber,\n  isString,\n  isUndefined,\n  throwError,\n} from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport { Readable } from 'stream';\nimport { renderStyleAttribute } from './prop-renderers';\nimport {\n  createDerivedState,\n  escapeText,\n  isAttributeNameSafe,\n  renderFunctionalComponent,\n  voidElements,\n} from './utils';\nimport { mergePendingState } from './stream/streamUtils';\n\nexport class RenderQueueStream extends Readable {\n  public collector: any[] = [Infinity]; // Infinity marks the end of the stream\n  public promises: any[] = [];\n\n  constructor(initNode) {\n    super();\n    this.pushQueue = this.pushQueue.bind(this);\n    if (initNode) {\n      this.renderVNodeToQueue(initNode, null, null);\n    }\n  }\n\n  public _read(): void {\n    setTimeout(this.pushQueue, 0);\n  }\n\n  public addToQueue(node, position): void {\n    // Positioning defined, stack it\n    if (!isNullOrUndef(position)) {\n      const lastSlot = this.promises[position].length - 1;\n      // Combine as array or push into promise collector\n      if (\n        typeof this.promises[position][lastSlot] === 'string' &&\n        typeof node === 'string'\n      ) {\n        this.promises[position][lastSlot] += node;\n      } else {\n        this.promises[position].push(node);\n      }\n      // Collector is empty push to stream\n    } else if (typeof node === 'string' && this.collector.length - 1 === 0) {\n      this.push(node);\n      // Last element in collector and incoming are same then concat\n    } else if (\n      typeof node === 'string' &&\n      typeof this.collector[this.collector.length - 2] === 'string'\n    ) {\n      this.collector[this.collector.length - 2] += node;\n      // Push the element to collector (before Infinity)\n    } else {\n      this.collector.splice(-1, 0, node);\n    }\n  }\n\n  public pushQueue(): void {\n    const chunk = this.collector[0];\n    // Output strings directly\n    if (typeof chunk === 'string') {\n      this.push(chunk);\n      this.collector.shift();\n      // For fulfilled promises, merge into collector\n    } else if (\n      !!chunk &&\n      (typeof chunk === 'object' || isFunction(chunk)) &&\n      isFunction(chunk.then)\n    ) {\n      chunk.then((index) => {\n        this.collector.splice(0, 1, ...this.promises[index]);\n        this.promises[index] = null;\n\n        setTimeout(this.pushQueue, 0);\n      });\n      this.collector[0] = null;\n      // End of content\n    } else if (chunk === Infinity) {\n      this.emit('end');\n    }\n  }\n\n  public renderVNodeToQueue(vNode, context, position): void {\n    const flags = vNode.flags;\n    const type = vNode.type;\n    const props = vNode.props || EMPTY_OBJ;\n    const children = vNode.children;\n\n    // Handles a component render\n    if ((flags & VNodeFlags.Component) > 0) {\n      const isClass = flags & VNodeFlags.ComponentClass;\n      // Render the\n      if (isClass) {\n        const instance = new type(props, context);\n        const hasNewAPI = Boolean(type.getDerivedStateFromProps);\n        instance.$BS = false;\n        instance.$SSR = true;\n        let childContext;\n        if (!isUndefined(instance.getChildContext)) {\n          childContext = instance.getChildContext();\n        }\n        if (!isNullOrUndef(childContext)) {\n          context = { ...context, ...childContext };\n        }\n        if (instance.props === EMPTY_OBJ) {\n          instance.props = props;\n        }\n        instance.context = context;\n        // Trigger lifecycle hook\n        if (!hasNewAPI && isFunction(instance.componentWillMount)) {\n          instance.$BR = true;\n          instance.componentWillMount();\n          mergePendingState(instance);\n        }\n        // Trigger extra promise-based lifecycle hook\n        if (isFunction(instance.getInitialProps)) {\n          const initialProps = instance.getInitialProps(\n            instance.props,\n            instance.context,\n          );\n          if (initialProps) {\n            if (Promise.resolve(initialProps) === initialProps) {\n              const promisePosition = this.promises.push([]) - 1;\n              this.addToQueue(\n                initialProps.then((dataForContext) => {\n                  if (typeof dataForContext === 'object') {\n                    instance.props = { ...instance.props, ...dataForContext };\n                  }\n\n                  const renderOut = instance.render(\n                    instance.props,\n                    instance.state,\n                    instance.context,\n                  );\n                  if (isInvalid(renderOut)) {\n                    this.addToQueue('<!--!-->', promisePosition);\n                  } else if (isString(renderOut)) {\n                    this.addToQueue(escapeText(renderOut), promisePosition);\n                  } else if (isNumber(renderOut)) {\n                    this.addToQueue(renderOut + '', promisePosition);\n                  } else {\n                    this.renderVNodeToQueue(\n                      renderOut,\n                      instance.context,\n                      promisePosition,\n                    );\n                  }\n\n                  setTimeout(this.pushQueue, 0);\n                  return promisePosition;\n                }),\n                position,\n              );\n              return;\n            } else {\n              instance.props = { ...instance.props, ...initialProps };\n            }\n          }\n        }\n        if (hasNewAPI) {\n          instance.state = createDerivedState(instance, props, instance.state);\n        }\n        const renderOutput = instance.render(\n          instance.props,\n          instance.state,\n          instance.context,\n        );\n\n        if (isInvalid(renderOutput)) {\n          this.addToQueue('<!--!-->', position);\n        } else if (isString(renderOutput)) {\n          this.addToQueue(escapeText(renderOutput), position);\n        } else if (isNumber(renderOutput)) {\n          this.addToQueue(renderOutput + '', position);\n        } else {\n          this.renderVNodeToQueue(renderOutput, context, position);\n        }\n      } else {\n        const renderOutput = renderFunctionalComponent(vNode, context);\n\n        if (isInvalid(renderOutput)) {\n          this.addToQueue('<!--!-->', position);\n        } else if (isString(renderOutput)) {\n          this.addToQueue(escapeText(renderOutput), position);\n        } else if (isNumber(renderOutput)) {\n          this.addToQueue(renderOutput + '', position);\n        } else {\n          this.renderVNodeToQueue(renderOutput, context, position);\n        }\n      }\n      // If an element\n    } else if ((flags & VNodeFlags.Element) > 0) {\n      let renderedString = `<${type}`;\n      let html;\n      const isVoidElement = voidElements.has(type);\n      const className = vNode.className;\n\n      if (isString(className)) {\n        renderedString += ` class=\"${escapeText(className)}\"`;\n      } else if (isNumber(className)) {\n        renderedString += ` class=\"${className}\"`;\n      }\n\n      if (!isNull(props)) {\n        for (const prop in props) {\n          const value = props[prop];\n\n          switch (prop) {\n            case 'dangerouslySetInnerHTML':\n              html = value.__html;\n              break;\n            case 'style':\n              if (!isNullOrUndef(props.style)) {\n                renderedString += renderStyleAttribute(props.style);\n              }\n              break;\n            case 'children':\n            case 'className':\n              // Ignore\n              break;\n            case 'defaultValue':\n              // Use default values if normal values are not present\n              if (!props.value) {\n                renderedString += ` value=\"${\n                  isString(value) ? escapeText(value) : value\n                }\"`;\n              }\n              break;\n            case 'defaultChecked':\n              // Use default values if normal values are not present\n              if (!props.checked && value === true) {\n                renderedString += ` checked=\"${value}\"`;\n              }\n              break;\n            default:\n              if (isAttributeNameSafe(prop)) {\n                if (isString(value)) {\n                  renderedString += ` ${prop}=\"${escapeText(value)}\"`;\n                } else if (isNumber(value)) {\n                  renderedString += ` ${prop}=\"${value}\"`;\n                } else if (value === true) {\n                  renderedString += ` ${prop}`;\n                }\n              }\n              break;\n          }\n        }\n      }\n      renderedString += `>`;\n\n      if (String(type).match(/[\\s\\n/='\"\\0<>]/)) {\n        throw renderedString;\n      }\n\n      // Voided element, push directly to queue\n      if (isVoidElement) {\n        this.addToQueue(renderedString, position);\n        // Regular element with content\n      } else {\n        // Element has children, build them in\n        const childFlags = vNode.childFlags;\n\n        if (childFlags === ChildFlags.HasVNodeChildren) {\n          this.addToQueue(renderedString, position);\n          this.renderVNodeToQueue(children, context, position);\n          this.addToQueue('</' + type + '>', position);\n          return;\n        } else if (childFlags === ChildFlags.HasTextChildren) {\n          this.addToQueue(renderedString, position);\n          this.addToQueue(\n            children === '' ? ' ' : escapeText(children + ''),\n            position,\n          );\n          this.addToQueue('</' + type + '>', position);\n          return;\n        } else if (childFlags & ChildFlags.MultipleChildren) {\n          this.addToQueue(renderedString, position);\n          for (let i = 0, len = children.length; i < len; ++i) {\n            this.renderVNodeToQueue(children[i], context, position);\n          }\n          this.addToQueue('</' + type + '>', position);\n          return;\n        }\n        if (html) {\n          this.addToQueue(renderedString + html + '</' + type + '>', position);\n          return;\n        }\n        // Close element if it's not void\n        if (!isVoidElement) {\n          this.addToQueue(renderedString + '</' + type + '>', position);\n        }\n      }\n      // Push text directly to queue\n    } else if ((flags & VNodeFlags.Text) > 0) {\n      this.addToQueue(children === '' ? ' ' : escapeText(children), position);\n      // Handle fragments and arrays\n    } else if (isArray(vNode) || (flags & VNodeFlags.Fragment) !== 0) {\n      const childFlags = vNode.childFlags;\n\n      if (\n        childFlags === ChildFlags.HasVNodeChildren ||\n        (isArray(vNode) && vNode.length === 0)\n      ) {\n        this.addToQueue('<!--!-->', position);\n      } else if (childFlags & ChildFlags.MultipleChildren || isArray(vNode)) {\n        const tmpChildren = isArray(vNode) ? vNode : vNode.children;\n\n        for (let i = 0, len = tmpChildren.length; i < len; ++i) {\n          this.renderVNodeToQueue(tmpChildren[i], context, position);\n        }\n      }\n      // Handle errors\n    } else {\n      if (process.env.NODE_ENV !== 'production') {\n        if (typeof vNode === 'object') {\n          throwError(\n            `renderToString() received an object that's not a valid VNode, you should stringify it first. Object: \"${JSON.stringify(\n              vNode,\n            )}\".`,\n          );\n        } else {\n          throwError(\n            `renderToString() expects a valid VNode, instead it received an object with the type \"${typeof vNode}\".`,\n          );\n        }\n      }\n      throwError();\n    }\n  }\n}\n\nexport function streamQueueAsString(node): RenderQueueStream {\n  return new RenderQueueStream(node);\n}\n"
  },
  {
    "path": "packages/inferno-server/src/renderToString.stream.ts",
    "content": "import {\n  isArray,\n  isFunction,\n  isInvalid,\n  isNull,\n  isNullOrUndef,\n  isNumber,\n  isString,\n} from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport { Readable } from 'stream';\nimport { renderStyleAttribute } from './prop-renderers';\nimport {\n  createDerivedState,\n  escapeText,\n  isAttributeNameSafe,\n  renderFunctionalComponent,\n  voidElements,\n} from './utils';\nimport type { VNode } from 'inferno';\nimport { mergePendingState } from './stream/streamUtils';\n\nconst resolvedPromise = Promise.resolve();\n\nexport class RenderStream extends Readable {\n  public initNode: any;\n  public started: boolean = false;\n\n  constructor(initNode) {\n    super();\n    this.initNode = initNode;\n  }\n\n  public _read(): void {\n    if (this.started) {\n      return;\n    }\n    this.started = true;\n\n    resolvedPromise\n      .then(() => {\n        return this.renderNode(this.initNode, null);\n      })\n      .then(() => {\n        this.push(null);\n      })\n      .catch((err) => {\n        this.emit('error', err);\n      });\n  }\n\n  public renderNode(vNode, context) {\n    const flags = vNode.flags;\n\n    if ((flags & VNodeFlags.Component) > 0) {\n      return this.renderComponent(\n        vNode,\n        context,\n        flags & VNodeFlags.ComponentClass,\n      );\n    }\n    if ((flags & VNodeFlags.Element) > 0) {\n      return this.renderElement(vNode, context);\n    }\n    if (isArray(vNode) || (flags & VNodeFlags.Fragment) !== 0) {\n      return this.renderArrayOrFragment(vNode, context);\n    }\n\n    this.renderText(vNode);\n  }\n\n  public renderArrayOrFragment(vNode, context) {\n    const childFlags = vNode.childFlags;\n\n    if (\n      childFlags === ChildFlags.HasVNodeChildren ||\n      (isArray(vNode) && vNode.length === 0)\n    ) {\n      return this.push('<!--!-->');\n    } else if (childFlags & ChildFlags.MultipleChildren || isArray(vNode)) {\n      const children = isArray(vNode) ? vNode : vNode.children;\n\n      return (children as VNode[]).reduce(async (p, child) => {\n        return await p.then(async () => {\n          return await Promise.resolve(this.renderNode(child, context)).then(\n            () => !!(child.flags & VNodeFlags.Text),\n          );\n        });\n      }, Promise.resolve(false));\n    }\n  }\n\n  public renderComponent(vComponent, context, isClass) {\n    const type = vComponent.type;\n    const props = vComponent.props;\n\n    if (!isClass) {\n      const renderOutput = renderFunctionalComponent(vComponent, context);\n\n      if (isInvalid(renderOutput)) {\n        return this.push('<!--!-->');\n      }\n      if (isString(renderOutput)) {\n        return this.push(escapeText(renderOutput));\n      }\n      if (isNumber(renderOutput)) {\n        return this.push(renderOutput + '');\n      }\n\n      return this.renderNode(renderOutput, context);\n    }\n\n    const instance = new type(props, context);\n    const hasNewAPI = Boolean(type.getDerivedStateFromProps);\n    instance.$BS = false;\n    instance.$SSR = true;\n    let childContext;\n    if (isFunction(instance.getChildContext)) {\n      childContext = instance.getChildContext();\n    }\n\n    if (!isNullOrUndef(childContext)) {\n      context = { ...context, ...childContext };\n    }\n    instance.context = context;\n    instance.$BR = true;\n\n    return Promise.resolve(!hasNewAPI && instance.componentWillMount?.()).then(\n      () => {\n        mergePendingState(instance);\n\n        if (hasNewAPI) {\n          instance.state = createDerivedState(instance, props, instance.state);\n        }\n        const renderOutput = instance.render(\n          instance.props,\n          instance.state,\n          instance.context,\n        );\n\n        if (isInvalid(renderOutput)) {\n          return this.push('<!--!-->');\n        }\n        if (isString(renderOutput)) {\n          return this.push(escapeText(renderOutput));\n        }\n        if (isNumber(renderOutput)) {\n          return this.push(renderOutput + '');\n        }\n\n        return this.renderNode(renderOutput, context);\n      },\n    );\n  }\n\n  public renderChildren(\n    children: VNode[] | VNode | string,\n    context: any,\n    childFlags: ChildFlags,\n  ) {\n    if (childFlags === ChildFlags.HasVNodeChildren) {\n      return this.renderNode(children, context);\n    }\n    if (childFlags === ChildFlags.HasTextChildren) {\n      return this.push(\n        (children as string) === ''\n          ? ' '\n          : escapeText((children as string) + ''),\n      );\n    }\n    if (childFlags & ChildFlags.MultipleChildren) {\n      return (children as VNode[]).reduce(async (p, child) => {\n        return await p.then(async () => {\n          return await Promise.resolve(this.renderNode(child, context)).then(\n            () => !!(child.flags & VNodeFlags.Text),\n          );\n        });\n      }, Promise.resolve(false));\n    }\n  }\n\n  public renderText(vNode): void {\n    this.push(vNode.children === '' ? ' ' : escapeText(vNode.children));\n  }\n\n  public renderElement(vNode, context) {\n    const type = vNode.type;\n    const props = vNode.props;\n    let renderedString = `<${type}`;\n    let html;\n    const isVoidElement = voidElements.has(type);\n    const className = vNode.className;\n\n    if (isString(className)) {\n      renderedString += ` class=\"${escapeText(className)}\"`;\n    } else if (isNumber(className)) {\n      renderedString += ` class=\"${className}\"`;\n    }\n\n    if (!isNull(props)) {\n      for (const prop in props) {\n        const value = props[prop];\n\n        switch (prop) {\n          case 'dangerouslySetInnerHTML':\n            html = value.__html;\n            break;\n          case 'style':\n            if (!isNullOrUndef(props.style)) {\n              renderedString += renderStyleAttribute(props.style);\n            }\n            break;\n          case 'children':\n          case 'className':\n            // Ignore\n            break;\n          case 'defaultValue':\n            // Use default values if normal values are not present\n            if (!props.value) {\n              renderedString += ` value=\"${\n                isString(value) ? escapeText(value) : value\n              }\"`;\n            }\n            break;\n          case 'defaultChecked':\n            // Use default values if normal values are not present\n            if (!props.checked && value === true) {\n              renderedString += ` checked=\"${value}\"`;\n            }\n            break;\n          default:\n            if (isAttributeNameSafe(prop)) {\n              if (isString(value)) {\n                renderedString += ` ${prop}=\"${escapeText(value)}\"`;\n              } else if (isNumber(value)) {\n                renderedString += ` ${prop}=\"${value}\"`;\n              } else if (value === true) {\n                renderedString += ` ${prop}`;\n              }\n              break;\n            }\n        }\n      }\n    }\n\n    renderedString += `>`;\n    this.push(renderedString);\n\n    if (String(type).match(/[\\s\\n/='\"\\0<>]/)) {\n      throw renderedString;\n    }\n\n    if (isVoidElement) {\n      return;\n    } else {\n      if (html) {\n        this.push(html);\n        this.push(`</${type}>`);\n        return;\n      }\n    }\n    const childFlags = vNode.childFlags;\n\n    if (childFlags === ChildFlags.HasInvalidChildren) {\n      this.push(`</${type}>`);\n      return;\n    }\n\n    return Promise.resolve(\n      this.renderChildren(vNode.children, context, childFlags),\n    ).then(() => {\n      this.push(`</${type}>`);\n    });\n  }\n}\n\nexport function streamAsString(node) {\n  return new RenderStream(node);\n}\n"
  },
  {
    "path": "packages/inferno-server/src/renderToString.ts",
    "content": "import { EMPTY_OBJ } from 'inferno';\nimport {\n  isArray,\n  isFunction,\n  isInvalid,\n  isNull,\n  isNullOrUndef,\n  isNumber,\n  isString,\n  throwError,\n} from 'inferno-shared';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport { renderStyleAttribute } from './prop-renderers';\nimport {\n  createDerivedState,\n  escapeText,\n  isAttributeNameSafe,\n  renderFunctionalComponent,\n  voidElements,\n} from './utils';\n\nfunction renderVNodeToString(vNode, parent, context): string {\n  const flags = vNode.flags;\n  const type = vNode.type;\n  const props = vNode.props || EMPTY_OBJ;\n  const children = vNode.children;\n\n  if ((flags & VNodeFlags.Component) !== 0) {\n    const isClass = flags & VNodeFlags.ComponentClass;\n\n    if (isClass) {\n      const instance = new type(props, context);\n      const hasNewAPI = Boolean(type.getDerivedStateFromProps);\n      instance.$BS = false;\n      instance.$SSR = true;\n      let childContext;\n      if (isFunction(instance.getChildContext)) {\n        childContext = instance.getChildContext();\n      }\n\n      if (isNullOrUndef(childContext)) {\n        childContext = context;\n      } else {\n        childContext = { ...context, ...childContext };\n      }\n      if (instance.props === EMPTY_OBJ) {\n        instance.props = props;\n      }\n      instance.context = context;\n      if (!hasNewAPI && isFunction(instance.componentWillMount)) {\n        instance.$BR = true;\n        instance.componentWillMount();\n        instance.$BR = false;\n        const pending = instance.$PS;\n\n        if (pending) {\n          const state = instance.state;\n\n          if (state === null) {\n            instance.state = pending;\n          } else {\n            for (const key in pending) {\n              state[key] = pending[key];\n            }\n          }\n          instance.$PSS = false;\n          instance.$PS = null;\n        }\n      }\n      if (hasNewAPI) {\n        instance.state = createDerivedState(instance, props, instance.state);\n      }\n      const renderOutput = instance.render(\n        props,\n        instance.state,\n        instance.context,\n      );\n      // In case render returns invalid stuff\n      if (isInvalid(renderOutput)) {\n        return '<!--!-->';\n      }\n      if (isString(renderOutput)) {\n        return escapeText(renderOutput);\n      }\n      if (isNumber(renderOutput)) {\n        return renderOutput + '';\n      }\n      return renderVNodeToString(renderOutput, vNode, childContext);\n    } else {\n      const renderOutput = renderFunctionalComponent(vNode, context);\n\n      if (isInvalid(renderOutput)) {\n        return '<!--!-->';\n      }\n      if (isString(renderOutput)) {\n        return escapeText(renderOutput);\n      }\n      if (isNumber(renderOutput)) {\n        return renderOutput + '';\n      }\n      return renderVNodeToString(renderOutput, vNode, context);\n    }\n  } else if ((flags & VNodeFlags.Element) !== 0) {\n    let renderedString = `<${type}`;\n    let html;\n\n    const isVoidElement = voidElements.has(type);\n    const className = vNode.className;\n\n    if (isString(className)) {\n      renderedString += ` class=\"${escapeText(className)}\"`;\n    } else if (isNumber(className)) {\n      renderedString += ` class=\"${className}\"`;\n    }\n\n    if (!isNull(props)) {\n      for (const prop in props) {\n        const value = props[prop];\n\n        switch (prop) {\n          case 'dangerouslySetInnerHTML':\n            html = value.__html;\n            break;\n          case 'style':\n            if (!isNullOrUndef(props.style)) {\n              renderedString += renderStyleAttribute(props.style);\n            }\n            break;\n          case 'children':\n          case 'className':\n            // Ignore\n            break;\n          case 'defaultValue':\n            // Use default values if normal values are not present\n            if (!props.value) {\n              renderedString += ` value=\"${\n                isString(value) ? escapeText(value) : value\n              }\"`;\n            }\n            break;\n          case 'defaultChecked':\n            // Use default values if normal values are not present\n            if (!props.checked && value === true) {\n              renderedString += ` checked=\"${value}\"`;\n            }\n            break;\n          default:\n            if (isAttributeNameSafe(prop)) {\n              if (isString(value)) {\n                renderedString += ` ${prop}=\"${escapeText(value)}\"`;\n              } else if (isNumber(value)) {\n                renderedString += ` ${prop}=\"${value}\"`;\n              } else if (value === true) {\n                renderedString += ` ${prop}`;\n              }\n            }\n\n            break;\n        }\n      }\n      if (\n        type === 'option' &&\n        typeof props.value !== 'undefined' &&\n        props.value === parent.props.value\n      ) {\n        // Parent value sets children value\n        renderedString += ` selected`;\n      }\n    }\n    if (isVoidElement) {\n      renderedString += `>`;\n    } else {\n      renderedString += `>`;\n      const childFlags = vNode.childFlags;\n\n      if (childFlags === ChildFlags.HasVNodeChildren) {\n        renderedString += renderVNodeToString(children, vNode, context);\n      } else if (childFlags & ChildFlags.MultipleChildren) {\n        for (let i = 0, len = children.length; i < len; ++i) {\n          renderedString += renderVNodeToString(children[i], vNode, context);\n        }\n      } else if (childFlags === ChildFlags.HasTextChildren) {\n        renderedString += children === '' ? ' ' : escapeText(children);\n      } else if (html) {\n        renderedString += html;\n      }\n      if (!isVoidElement) {\n        renderedString += `</${type}>`;\n      }\n    }\n\n    if (String(type).match(/[\\s\\n/='\"\\0<>]/)) {\n      throw renderedString;\n    }\n\n    return renderedString;\n  } else if ((flags & VNodeFlags.Text) !== 0) {\n    return children === '' ? ' ' : escapeText(children);\n  } else if (isArray(vNode) || (flags & VNodeFlags.Fragment) !== 0) {\n    const childFlags = vNode.childFlags;\n\n    if (\n      childFlags === ChildFlags.HasVNodeChildren ||\n      (isArray(vNode) && vNode.length === 0)\n    ) {\n      return '<!--!-->';\n    } else if (childFlags & ChildFlags.MultipleChildren || isArray(vNode)) {\n      const tmpNodes = isArray(vNode) ? vNode : children;\n      let renderedString = '';\n\n      for (let i = 0, len = tmpNodes.length; i < len; ++i) {\n        renderedString += renderVNodeToString(tmpNodes[i], vNode, context);\n      }\n\n      return renderedString;\n    }\n  } else {\n    if (process.env.NODE_ENV !== 'production') {\n      if (typeof vNode === 'object') {\n        throwError(\n          `renderToString() received an object that's not a valid VNode, you should stringify it first. Object: \"${JSON.stringify(\n            vNode,\n          )}\".`,\n        );\n      } else {\n        throwError(\n          `renderToString() expects a valid VNode, instead it received an object with the type \"${typeof vNode}\".`,\n        );\n      }\n    }\n    throwError();\n  }\n\n  return '';\n}\n\nexport function renderToString(input: any): string {\n  return renderVNodeToString(input, {}, {});\n}\n"
  },
  {
    "path": "packages/inferno-server/src/stream/streamUtils.ts",
    "content": "export function mergePendingState(componentInstance): void {\n  const pendingState = componentInstance.$PS;\n\n  if (pendingState) {\n    const state = componentInstance.state;\n\n    if (state === null) {\n      componentInstance.state = pendingState;\n    } else {\n      componentInstance.state = { ...state, ...pendingState };\n    }\n    componentInstance.$PS = null;\n  }\n\n  componentInstance.$BR = false;\n}\n"
  },
  {
    "path": "packages/inferno-server/src/utils.ts",
    "content": "import { EMPTY_OBJ, type InfernoNode, type VNode } from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nconst rxUnescaped = /[\"'&<>]/;\n\nexport function escapeText(text: string): string {\n  /* Much faster when there is no unescaped characters */\n  if (!rxUnescaped.test(text)) {\n    return text;\n  }\n\n  let result = '';\n  // assigning empty string here tells JIT this is text\n  // eslint-disable-next-line no-useless-assignment\n  let escape = '';\n  let start = 0;\n  let i = 0;\n  for (; i < text.length; ++i) {\n    switch (text.charCodeAt(i)) {\n      case 34: // \"\n        escape = '&quot;';\n        break;\n      case 39: // '\n        escape = '&#039;';\n        break;\n      case 38: // &\n        escape = '&amp;';\n        break;\n      case 60: // <\n        escape = '&lt;';\n        break;\n      case 62: // >\n        escape = '&gt;';\n        break;\n      default:\n        continue;\n    }\n    if (i > start) {\n      result += text.slice(start, i);\n    }\n    result += escape;\n    start = i + 1;\n  }\n  return result + text.slice(start, i);\n}\n\nconst uppercasePattern = /[A-Z]/g;\n\nconst CssPropCache = {};\n\nexport function getCssPropertyName(str): string {\n  if (CssPropCache[str] !== void 0) {\n    return CssPropCache[str];\n  }\n  return (CssPropCache[str] =\n    str.replace(uppercasePattern, '-$&').toLowerCase() + ':');\n}\n\nconst ATTRIBUTE_NAME_START_CHAR =\n  ':A-Z_a-z\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD';\n\nconst ATTRIBUTE_NAME_CHAR =\n  ATTRIBUTE_NAME_START_CHAR + '\\\\-.0-9\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040';\n\nexport const VALID_ATTRIBUTE_NAME_REGEX = new RegExp(\n  // eslint-disable-next-line no-misleading-character-class\n  '^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$',\n);\n\nconst illegalAttributeNameCache = {};\nconst validatedAttributeNameCache = {};\n\nexport function isAttributeNameSafe(attributeName: string): boolean {\n  if (validatedAttributeNameCache[attributeName] !== void 0) {\n    return true;\n  }\n  if (illegalAttributeNameCache[attributeName] !== void 0) {\n    return false;\n  }\n  if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {\n    validatedAttributeNameCache[attributeName] = true;\n    return true;\n  }\n  illegalAttributeNameCache[attributeName] = true;\n  if (process.env.NODE_ENV !== 'production') {\n    console.log('Invalid attribute name: ' + attributeName);\n  }\n  return false;\n}\n\nexport const voidElements = new Set([\n  'area',\n  'base',\n  'br',\n  'col',\n  'command',\n  'embed',\n  'hr',\n  'img',\n  'input',\n  'keygen',\n  'link',\n  'meta',\n  'param',\n  'source',\n  'track',\n  'wbr',\n]);\n\nexport function createDerivedState(\n  instance,\n  nextProps,\n  state,\n): Record<string, unknown> {\n  if (instance.constructor.getDerivedStateFromProps) {\n    return {\n      ...state,\n      ...instance.constructor.getDerivedStateFromProps(nextProps, state),\n    };\n  }\n\n  return state;\n}\n\nexport function renderFunctionalComponent(vNode: VNode, context): InfernoNode {\n  const props = vNode.props || EMPTY_OBJ;\n  return vNode.flags & VNodeFlags.ForwardRef\n    ? vNode.type.render(props, vNode.ref, context)\n    : vNode.type(props, context);\n}\n"
  },
  {
    "path": "packages/inferno-shared/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-shared/package.json",
    "content": "{\n  \"name\": \"inferno-shared\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Helpers functions for Inferno\",\n  \"author\": {\n    \"name\": \"Dominic Gannaway\",\n    \"email\": \"dg@domgan.com\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"files\": [\n    \"index.cjs\",\n    \"dist/\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"keywords\": [\n    \"inferno\",\n    \"helpers\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-shared\"\n  },\n  \"rollup\": {\n    \"moduleName\": \"Inferno\"\n  }\n}\n"
  },
  {
    "path": "packages/inferno-shared/src/index.ts",
    "content": "import type { VNode } from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nexport const ERROR_MSG =\n  'a runtime error occured! Use Inferno in development environment to find the error.';\n\nexport const isArray = Array.isArray;\n\nexport function isStringOrNumber(o: unknown): o is string | number {\n  const type = typeof o;\n\n  return type === 'string' || type === 'number';\n}\n\nexport function isNullOrUndef(o: unknown): o is undefined | null {\n  return o === void 0 || o === null;\n}\n\nexport function isInvalid(o: unknown): o is null | boolean | undefined {\n  return o === null || o === false || o === true || o === void 0;\n}\n\nexport function isFunction(o: unknown): o is Function {\n  return typeof o === 'function';\n}\n\nexport function isString(o: unknown): o is string {\n  return typeof o === 'string';\n}\n\nexport function isNumber(o: unknown): o is number {\n  return typeof o === 'number';\n}\n\nexport function isNull(o: unknown): o is null {\n  return o === null;\n}\n\nexport function isUndefined(o: unknown): o is undefined {\n  return o === void 0;\n}\n\nexport function throwError(message?: string): void {\n  if (!message) {\n    message = ERROR_MSG;\n  }\n  throw new Error(`Inferno Error: ${message}`);\n}\n\nexport function warning(message: string): void {\n  console.error(message);\n}\n\nconst KNOWN_STATICS = {\n  childContextTypes: true,\n  contextType: true,\n  contextTypes: true,\n  defaultProps: true,\n  displayName: true,\n  getDefaultProps: true,\n  getDerivedStateFromError: true,\n  getDerivedStateFromProps: true,\n  mixins: true,\n  propTypes: true,\n  type: true,\n  // KNOWN STATICS\n  name: true,\n  length: true,\n  prototype: true,\n  caller: true,\n  callee: true,\n  arguments: true,\n  arity: true,\n};\n\nexport function hoistStaticProperties(\n  targetComponent: any,\n  sourceComponent: any,\n): void {\n  // don't hoist over string (html) components\n  const keys = Object.getOwnPropertyNames(sourceComponent);\n\n  for (let i = 0; i < keys.length; ++i) {\n    const key = keys[i];\n\n    if (!KNOWN_STATICS[key]) {\n      targetComponent[key] = sourceComponent[key];\n    }\n  }\n}\n\nexport function isValidElement(obj: VNode): boolean {\n  const isValidObject = typeof obj === 'object' && !isNull(obj);\n\n  if (!isValidObject) {\n    return false;\n  }\n\n  return (obj.flags & (VNodeFlags.Component | VNodeFlags.Element)) > 0;\n}\n\n"
  },
  {
    "path": "packages/inferno-test-utils/README.md",
    "content": "# inferno-test-utils\n\n> Suite of utilities for testing Inferno applications\n\n## Install\n\n```\nnpm install inferno --save\nnpm install inferno-test-utils --save-dev\n```\n\n## Contents\n\n- [`findAllInRenderedTree`](#findallinrenderedtreerenderedtree-predicate)\n- [`findAllInVNodeTree`](#findallinvnodetreevnodetree-predicate)\n- [`scryRenderedDOMElementsWithClass`](#scryrendereddomelementswithclassrenderedtree-classnames)\n- [`findRenderedDOMElementWithClass`](#findrendereddomelementwithclassrenderedtree-classnames)\n- [`scryRenderedDOMElementsWithTag`](#scryrendereddomelementswithtagrenderedtree-tagname)\n- [`findRenderedDOMElementWithTag`](#findrendereddomelementwithtagrenderedtree-tagname)\n- [`scryRenderedVNodesWithType`](#scryrenderedvnodeswithtyperenderedtree-type)\n- [`findRenderedVNodeWithType`](#findrenderedvnodewithtyperenderedtree-type)\n- [`scryVNodesWithType`](#scryvnodeswithtypevnodetree-type)\n- [`findVNodeWithType`](#findvnodewithtypevnodetree-type)\n- [`isVNode`](#isvnodeinstance)\n- [`isVNodeOfType`](#isvnodeoftypeinstance-type)\n- [`isDOMVNode`](#isdomvnodeinstance)\n- [`isDOMVNodeOfType`](#isdomvnodeoftypeinstance-type)\n- [`isFunctionalVNode`](#isfunctionalvnodeinstance)\n- [`isFunctionalVNodeOfType`](#isfunctionalvnodeoftypeinstance-type)\n- [`isClassVNode`](#isclassvnodeinstance)\n- [`isClassVNodeOfType`](#isclassvnodeoftypeinstance-type)\n- [`isDOMElement`](#isdomelementinstance)\n- [`isDOMElementOfType`](#isdomelementoftypeinstance-type)\n- [`isRenderedClassComponent`](#isrenderedclasscomponentinstance)\n- [`isRenderedClassComponentOfType`](#isrenderedclasscomponentoftypeinstance-type)\n- [`renderIntoContainer`](#renderIntoContainervnodetree)\n\n## Usage\n\n### `renderIntoContainer(vNodeTree)`\n\nRenders `vNodeTree` into a detached DOM element in the document and returns a rendered `VNode` tree.\n\n_This function requires a DOM. JEST can provide this for you_.\n\n```js\nconst vNodeTree = (\n  <div className=\"outer\">\n    <SomeComponent className=\"inner\" />\n  </div>\n);\nconst renderedTree = renderIntoContainer(vNodeTree);\n```\n\n### `findAllInRenderedTree(renderedTree, predicate)`\n\nCalls `predicate` with each `VNode` instance in `renderedTree`.\n\nReturns an array of `VNodes` where `predicate` returns `true`.\n\n```js\nconst vNodeTree = (\n  <div className=\"outer\">\n    <SomeComponent className=\"inner\" />\n  </div>\n);\nconst renderedTree = render(vNodeTree, DOM);\nconst predicate = (vNode) => vNode.type === SomeComponent;\nconst result = findAllInRenderedTree(renderedTree, predicate);\n```\n\n### `findAllInVNodeTree(vNodeTree, predicate)`\n\nCalls `predicate` with each `VNode` instance in `vNodeTree`.\n\nReturns an array of `VNodes` where `predicate` returns `true`.\n\n```js\nconst vNodeTree = (\n  <div className=\"outer\">\n    <SomeComponent className=\"inner\" />\n  </div>\n);\nconst predicate = (vNode) => vNode.type === SomeComponent;\nconst result = findAllInVNodeTree(vNodeTree, predicate);\n```\n\n### `scryRenderedDOMElementsWithClass(renderedTree, classNames)`\n\nReturns an array of DOM elements with `classNames`.\n\n`classNames` can be a space-separated string or an array of strings.\n\n```js\nconst vNodeTree = (\n  <div className=\"outer\">\n    <SomeComponent className=\"inner one\" />\n    <SomeComponent className=\"inner two\" />\n  </div>\n);\nconst renderedTree = render(vNodeTree, DOM);\nconst result1 = scryRenderedDOMElementsWithClass(renderedTree, 'inner');\nconst result2 = scryRenderedDOMElementsWithClass(renderedTree, 'inner one');\nconst result3 = scryRenderedDOMElementsWithClass(renderedTree, [\n  'inner',\n  'two',\n]);\nconst result4 = scryRenderedDOMElementsWithClass(renderedTree, 'three'); // Empty array\n```\n\n### `findRenderedDOMElementWithClass(renderedTree, classNames)`\n\nReturns a single DOM element with `classNames`. If more than one matches are found, throws an error.\n\n`classNames` can be a space-separated string or an array of strings.\n\n```js\nconst vNodeTree = (\n  <div className=\"outer\">\n    <SomeComponent className=\"inner one\" />\n    <SomeComponent className=\"inner two\" />\n  </div>\n);\nconst renderedTree = render(vNodeTree, DOM);\nconst result1 = scryRenderedDOMElementsWithClass(renderedTree, 'outer');\nconst result2 = scryRenderedDOMElementsWithClass(renderedTree, 'inner one');\n// Will throw an error because more than 1 matches were found...\nconst result3 = scryRenderedDOMElementsWithClass(renderedTree, 'inner');\n```\n\n### `scryRenderedDOMElementsWithTag(renderedTree, tagName)`\n\nReturns an array of DOM elements with `tagName`.\n\n```js\nconst vNodeTree = (\n  <div>\n    <h1>Heading</h1>\n    <p>Paragraph One</p>\n    <p>Paragraph Two</p>\n    <p>Paragraph Three</p>\n  </div>\n);\nconst renderedTree = render(vNodeTree, DOM);\nconst result1 = scryRenderedDOMElementsWithTag(renderedTree, 'h1');\nconst result3 = scryRenderedDOMElementsWithTag(renderedTree, 'p');\nconst result4 = scryRenderedVNodesWithType(renderedTree, 'span'); // Empty array\n```\n\n### `findRenderedDOMElementWithTag(renderedTree, tagName)`\n\nReturns a single DOM element with `tagName`. If more than one matches are found, throws an error.\n\n```js\nconst vNodeTree = (\n  <div>\n    <h1>Heading</h1>\n    <div>\n      <p>Paragraph One</p>\n      <p>Paragraph Two</p>\n      <p>Paragraph Three</p>\n    </div>\n  </div>\n);\nconst renderedTree = render(vNodeTree, DOM);\nconst result1 = findRenderedDOMElementWithTag(renderedTree, 'h1');\n// Will throw an error because more than 1 matches were found...\nconst result2 = findRenderedDOMElementWithTag(renderedTree, 'p');\n```\n\n### `scryRenderedVNodesWithType(renderedTree, type)`\n\nReturns an array of rendered `VNodes` with `type`.\n\n```js\nconst vNodeTree = (\n  <div>\n    <h1>Heading</h1>\n    <SomeComponent />\n    <SomeComponent />\n  </div>\n);\nconst renderedTree = render(vNodeTree, DOM);\nconst result1 = scryRenderedVNodesWithType(renderedTree, 'h1');\nconst result2 = scryRenderedVNodesWithType(renderedTree, SomeComponent);\nconst result3 = scryRenderedVNodesWithType(renderedTree, 'p'); // Empty array\n```\n\n### `findRenderedVNodeWithType(renderedTree, type)`\n\nReturns a single rendered `VNode` with `type`. If more than one matches are found, throws an error.\n\n```js\nconst vNodeTree = (\n  <div>\n    <h1>Heading</h1>\n    <p>Paragraph 1</p>\n    <p>Paragraph 2</p>\n    <SomeComponent />\n    <AnotherComponent />\n    <AnotherComponent />\n  </div>\n);\nconst renderedTree = render(vNodeTree, DOM);\nconst result1 = findRenderedVNodeWithType(renderedTree, 'h1');\nconst result2 = findRenderedVNodeWithType(renderedTree, SomeComponent);\n// Will throw an error because more than 1 matches were found...\nconst result3 = findRenderedVNodeWithType(renderedTree, 'p');\nconst result4 = findRenderedVNodeWithType(renderedTree, AnotherComponent);\n```\n\n### `scryVNodesWithType(vNodeTree, type)`\n\nReturns an array of `VNode` instances with `type`.\n\n```js\nconst vNodeTree = (\n  <div>\n    <h1>Heading</h1>\n    <SomeComponent />\n    <SomeComponent />\n  </div>\n);\nconst result1 = scryVNodesWithType(vNodeTree, 'h1');\nconst result2 = scryVNodesWithType(vNodeTree, SomeComponent);\nconst result3 = scryVNodesWithType(vNodeTree, 'p'); // Empty array\n```\n\n### `findVNodeWithType(vNodeTree, type)`\n\nReturns a single `VNode` instance with `type`. If more than one matches are found, throws an error.\n\n```js\nconst vNodeTree = (\n  <div>\n    <h1>Heading</h1>\n    <SomeComponent />\n    <SomeComponent />\n  </div>\n);\nconst result1 = findVNodeWithType(vNodeTree, 'h1');\n// Will throw an error because more than 1 matches were found...\nconst result2 = findVNodeWithType(vNodeTree, SomeComponent);\n```\n\n### `isVNode(instance)`\n\nReturns `true` when `instance` is a `VNode`.\n\n### `isVNodeOfType(instance, type)`\n\nReturns `true` when `instance` is a `VNode` of `type`.\n\n### `isDOMVNode(instance)`\n\nReturns `true` when `instance` is a DOM-type `VNode`.\n\n### `isDOMVNodeOfType(instance, type)`\n\nReturns `true` when `instance` is a DOM-type `VNode` of `type`.\n\n### `isFunctionalVNode(instance)`\n\nReturns `true` when `instance` is a functional-type `VNode`.\n\n### `isFunctionalVNodeOfType(instance, type)`\n\nReturns `true` when `instance` is a functional-type `VNode` of `type`.\n\n### `isClassVNode(instance)`\n\nReturns `true` when `instance` is a class-type `VNode`.\n\n### `isClassVNodeOfType(instance, type)`\n\nReturns `true` when `instance` is a class-type `VNode` of `type`.\n\n### `isDOMElement(instance)`\n\nReturns `true` when `instance` is a DOM element.\n\n### `isDOMElementOfType(instance, type)`\n\nReturns `true` when `instance` is a DOM element of `type`.\n\n### `isRenderedClassComponent(instance)`\n\nReturns `true` when `instance` is a rendered class `VNode`.\n\n### `isRenderedClassComponentOfType(instance, type)`\n\nReturns `true` when `instance` is a rendered class `VNode` of `type`.\n"
  },
  {
    "path": "packages/inferno-test-utils/__tests__/__snapshots__/snapshots.spec.tsx.snap",
    "content": "// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing\n\nexports[`Snapshots JSX Should flush setStates before building snapshot 1`] = `\n<div\n  className=\"App\"\n>\n  <header\n    className=\"App-header\"\n  >\n    <img\n      alt=\"logo\"\n      className=\"App-logo\"\n      src=\"logo\"\n    />\n    <p>\n      Edit \n      <code>\n        src/App.js\n      </code>\n       and save to reload.\n    </p>\n    <a\n      className=\"App-link\"\n      href=\"https://reactjs.org\"\n      rel=\"noopener noreferrer\"\n      target=\"_blank\"\n    >\n      ##BAR##\n    </a>\n  </header>\n</div>\n`;\n\nexports[`Snapshots JSX Should not fail when returning children array from component root, Github #1404 1`] = `\n[\n  <label />,\n  <span>\n    o\n  </span>,\n  <span>\n    k\n  </span>,\n]\n`;\n\nexports[`Snapshots JSX Should not fail when returning children array from component root, which contains text node. Github #1404 1`] = `\n[\n  <label />,\n  <span>\n    o\n  </span>,\n  <span>\n    k\n  </span>,\n  \"asd\",\n  \"1\",\n]\n`;\n\nexports[`Snapshots JSX Should render attributes and className 1`] = `\n<div\n  className=\"Testing\"\n/>\n`;\n\nexports[`Snapshots JSX Should render component children 1`] = `\n<div\n  className=\"Testing\"\n>\n  <div\n    className=\"ok\"\n  >\n    ABC\n  </div>\n</div>\n`;\n\nexports[`Snapshots JSX Should render deeper component 1`] = `\n<div\n  aria-rowindex={1}\n  className=\"okay\"\n  onClick={[Function]}\n>\n  <div>\n    Okay\n    <div>\n      <ul>\n        <li>\n          Okay\n        </li>\n      </ul>\n    </div>\n    <span\n      className=\"yea\"\n    />\n  </div>\n</div>\n`;\n\nexports[`Snapshots JSX Should render fragment 1`] = `\n<div>\n  [\n    <div\n      id=\"a1\"\n    >\n      A1\n    </div>,\n    <div>\n      A2\n    </div>,\n  ]\n  [\n    <div\n      id=\"b1\"\n    >\n      B1\n    </div>,\n  ]\n  [\n    <div\n      id=\"c1\"\n    >\n      C1\n    </div>,\n    <div>\n      C2\n    </div>,\n    <div>\n      C3\n    </div>,\n  ]\n</div>\n`;\n\nexports[`Snapshots JSX Should render fragment from component root 1`] = `\n<div>\n  1\n</div>\n`;\n\nexports[`Snapshots JSX Should render fragment root 1`] = `\n[\n  <div>\n    First\n  </div>,\n  <div>\n    Second\n  </div>,\n]\n`;\n\nexports[`Snapshots JSX Should render html element 1`] = `\n<a\n  aria-colspan={3}\n  className=\"foo\"\n  onClick={[Function]}\n>\n  Bar\n</a>\n`;\n\nexports[`Snapshots JSX Should render multiple elements 1`] = `\n<span>\n  <a>\n    T\n  </a>\n  <span\n    className=\"foo\"\n  >\n    est\n  </span>\n  12\n  Extra\n</span>\n`;\n"
  },
  {
    "path": "packages/inferno-test-utils/__tests__/__snapshots__/testUtils.jest.spec.tsx.snap",
    "content": "// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing\n\nexports[`renderToSnapshot should return a snapshot from a valid vNode 1`] = `\n<div\n  foo=\"bar\"\n/>\n`;\n\nexports[`renderToSnapshot should return a snapshot with className prop 1`] = `\n<div\n  className=\"test\"\n>\n  Test\n</div>\n`;\n\nexports[`renderToSnapshot should return a snapshot with className prop, multiple children 1`] = `\n<div\n  className=\"test\"\n>\n  <span>\n    a\n  </span>\n  <span>\n    b\n  </span>\n  <span>\n    1\n  </span>\n</div>\n`;\n"
  },
  {
    "path": "packages/inferno-test-utils/__tests__/snapshots.spec.tsx",
    "content": "import { Component, createFragment, Fragment, InfernoNode } from 'inferno';\nimport { renderToSnapshot } from 'inferno-test-utils';\nimport { ChildFlags } from 'inferno-vnode-flags';\n\nif ((window as any).usingJest) {\n  describe('Snapshots', () => {\n    class Foobar extends Component<{ children?: InfernoNode }> {\n      render({ children }) {\n        return <div className=\"Testing\">{children}</div>;\n      }\n    }\n\n    function Testing({ children }) {\n      return (\n        <span>\n          {children}\n          Extra\n        </span>\n      );\n    }\n\n    describe('JSX', () => {\n      it('Should render attributes and className', () => {\n        expect(renderToSnapshot(<Foobar />)).toMatchSnapshot();\n      });\n\n      it('Should render component children', () => {\n        expect(\n          renderToSnapshot(\n            <Foobar>\n              <div className=\"ok\">ABC</div>\n            </Foobar>,\n          ),\n        ).toMatchSnapshot();\n      });\n\n      it('Should render html element', () => {\n        expect(\n          renderToSnapshot(\n            <a onClick={() => {}} aria-colspan={3} className=\"foo\">\n              Bar\n            </a>,\n          ),\n        ).toMatchSnapshot();\n      });\n\n      it('Should render multiple elements', () => {\n        expect(\n          renderToSnapshot(\n            <Testing>\n              <a>T</a>\n              <span className=\"foo\">est</span>\n              12\n            </Testing>,\n          ),\n        ).toMatchSnapshot();\n      });\n\n      it('Should render deeper component', () => {\n        class ComP extends Component {\n          render() {\n            return (\n              <div>\n                Okay\n                {this.props.children}\n                <span className=\"yea\" />\n              </div>\n            );\n          }\n        }\n\n        expect(\n          renderToSnapshot(\n            <div className=\"okay\" aria-rowindex={1} onClick={() => console.log}>\n              <ComP>\n                <div>\n                  <ul>\n                    <li>Okay</li>\n                  </ul>\n                </div>\n              </ComP>\n            </div>,\n          ),\n        ).toMatchSnapshot();\n      });\n\n      it('Should render fragment', () => {\n        const fragmentA = createFragment(\n          [<div id=\"a1\">A1</div>, <div>A2</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'A',\n        );\n\n        const fragmentB = createFragment(\n          [<div id=\"b1\">B1</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'B',\n        );\n\n        const fragmentC = createFragment(\n          [<div id=\"c1\">C1</div>, <div>C2</div>, <div>C3</div>],\n          ChildFlags.HasNonKeyedChildren,\n          'C',\n        );\n\n        expect(\n          renderToSnapshot(\n            <div>\n              {fragmentA}\n              {fragmentB}\n              {fragmentC}\n            </div>,\n          ),\n        ).toMatchSnapshot();\n      });\n\n      it('Should render fragment root', () => {\n        expect(\n          renderToSnapshot(\n            <Fragment>\n              <div>First</div>\n              <div>Second</div>\n            </Fragment>,\n          ),\n        ).toMatchSnapshot();\n      });\n\n      it('Should render fragment from component root', () => {\n        class Comp extends Component {\n          render() {\n            return <>{this.props.children}</>;\n          }\n        }\n\n        expect(\n          renderToSnapshot(\n            <Comp>\n              <div>1</div>\n            </Comp>,\n          ),\n        ).toMatchSnapshot();\n      });\n\n      it('Should not fail when returning children array from component root, which contains text node. Github #1404', () => {\n        interface LabelProps {\n          label?: string;\n          htmlFor?: string;\n          optional?: boolean;\n          children: any;\n        }\n        const Label = ({\n          label,\n          htmlFor,\n          children,\n          optional = false,\n          ...props\n        }: LabelProps) => {\n          if (optional && !label) {\n            return children;\n          }\n          return (\n            <>\n              <label {...props} htmlFor={htmlFor}>\n                {label}\n              </label>\n              {children}\n            </>\n          );\n        };\n        expect(\n          renderToSnapshot(\n            <Label>\n              {[\n                <span>o</span>,\n                <span>k</span>,\n                'asd',\n                1,\n                null,\n                false,\n                true,\n                void 0,\n              ]}\n            </Label>,\n          ),\n        ).toMatchSnapshot();\n      });\n\n      it('Should not fail when returning children array from component root, Github #1404', () => {\n        interface LabelProps {\n          label?: string;\n          htmlFor?: string;\n          optional?: boolean;\n          children: any;\n        }\n        const Label = ({\n          label,\n          htmlFor,\n          children,\n          optional = false,\n          ...props\n        }: LabelProps) => {\n          if (optional && !label) {\n            return children;\n          }\n\n          return (\n            <>\n              <label {...props} htmlFor={htmlFor}>\n                {label}\n              </label>\n              {children}\n            </>\n          );\n        };\n\n        expect(\n          renderToSnapshot(<Label>{[<span>o</span>, <span>k</span>]}</Label>),\n        ).toMatchSnapshot();\n      });\n\n      it('Should flush setStates before building snapshot', () => {\n        class App extends Component {\n          state = {\n            foo: '',\n          };\n\n          componentDidMount() {\n            this.setState({\n              foo: '##BAR##',\n            });\n          }\n\n          render() {\n            return (\n              <div className=\"App\">\n                <header className=\"App-header\">\n                  <img src=\"logo\" className=\"App-logo\" alt=\"logo\" />\n                  <p>\n                    Edit <code>src/App.js</code> and save to reload.\n                  </p>\n                  <a\n                    className=\"App-link\"\n                    href=\"https://reactjs.org\"\n                    target=\"_blank\"\n                    rel=\"noopener noreferrer\"\n                  >\n                    {this.state.foo}\n                  </a>\n                </header>\n              </div>\n            );\n          }\n        }\n\n        expect(renderToSnapshot(<App />)).toMatchSnapshot();\n      });\n    });\n  });\n}\n"
  },
  {
    "path": "packages/inferno-test-utils/__tests__/testUtils.jest.spec.tsx",
    "content": "import { createElement } from 'inferno-create-element';\nimport * as TestUtils from 'inferno-test-utils';\n\nconst FunctionalComponent = function (props) {\n  return createElement('div', props);\n};\n\nconst usingJest = (window as any).usingJest as boolean;\n\ndescribe('renderToSnapshot', () => {\n  it('should return a snapshot from a valid vNode', () => {\n    const snapshot = TestUtils.renderToSnapshot(\n      <FunctionalComponent foo=\"bar\" />,\n    );\n\n    if (usingJest) {\n      expect(snapshot).toMatchSnapshot();\n    } else {\n      expect(snapshot.props.foo).toBeDefined();\n      expect(snapshot.props.foo).toBe('bar');\n    }\n  });\n\n  it('should return a snapshot with className prop', () => {\n    const TestComponent = () => <div className=\"test\">Test</div>;\n\n    const snapshot = TestUtils.renderToSnapshot(<TestComponent />);\n\n    if (usingJest) {\n      expect(snapshot).toMatchSnapshot();\n    } else {\n      expect(snapshot.props.className).toBe('test');\n    }\n  });\n\n  it('should return a snapshot with className prop, multiple children', () => {\n    const TestComponent = (props) => (\n      <div className=\"test\">\n        {props.children}\n        <span>1</span>\n      </div>\n    );\n\n    const snapshot = TestUtils.renderToSnapshot(\n      <TestComponent>{[<span>a</span>, <span>b</span>]}</TestComponent>,\n    );\n\n    if (usingJest) {\n      expect(snapshot).toMatchSnapshot();\n    } else {\n      expect(snapshot.props.className).toBe('test');\n    }\n  });\n});\n"
  },
  {
    "path": "packages/inferno-test-utils/__tests__/testUtils.spec.tsx",
    "content": "import { Component, render } from 'inferno';\nimport { createElement } from 'inferno-create-element';\nimport {\n  findAllInRenderedTree,\n  findAllInVNodeTree,\n  findRenderedDOMElementWithClass,\n  findRenderedDOMElementWithTag,\n  findRenderedVNodeWithType,\n  findVNodeWithType,\n  isClassVNode,\n  isClassVNodeOfType,\n  isComponentVNodeOfType,\n  isDOMElement,\n  isDOMElementOfType,\n  isDOMVNode,\n  isDOMVNodeOfType,\n  isFunctionalVNode,\n  isFunctionalVNodeOfType,\n  isRenderedClassComponent,\n  isRenderedClassComponentOfType,\n  isVNode,\n  isVNodeOfType,\n  renderIntoContainer,\n  scryRenderedDOMElementsWithClass,\n  scryRenderedDOMElementsWithTag,\n  scryRenderedVNodesWithType,\n  scryVNodesWithType,\n} from 'inferno-test-utils';\n\nconst VNodeKeys = [\n  'children',\n  'childFlags',\n  'className',\n  'dom',\n  'flags',\n  'isValidated',\n  'key',\n  'ref',\n  'props',\n  'type',\n].sort();\n\nconst createDOMElement = (tagName) => document.createElement(tagName);\n\nconst FunctionalComponent = function (props) {\n  return createElement('div', props);\n};\n\nconst AnotherFunctionalComponent = function (props) {\n  return createElement('div', props);\n};\n\nclass ClassComponent extends Component {\n  render() {\n    return createElement('div', this.props);\n  }\n}\n\nclass AnotherClassComponent extends Component {\n  render() {\n    return createElement('div', this.props);\n  }\n}\n\nclass ExtendClassComponent extends Component {\n  render() {\n    return createElement('div', this.props);\n  }\n}\n\nclass AnotherExtendClassComponent extends Component {\n  render() {\n    return createElement('div', this.props);\n  }\n}\n\ndescribe('Test Utils', () => {\n  let container;\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    document.body.appendChild(container);\n  });\n\n  afterEach(() => {\n    render(null, container);\n    container.innerHTML = '';\n  });\n\n  describe('isVNode', () => {\n    it('should return true for VNodes', () => {\n      expect(isVNode(createElement('div'))).toBe(true);\n      expect(isVNode(createElement(ClassComponent))).toBe(true);\n      expect(isVNode(createElement(ExtendClassComponent))).toBe(true);\n      expect(isVNode(createElement(FunctionalComponent))).toBe(true);\n      expect(isVNode(<ClassComponent />)).toBe(true);\n      expect(isVNode(<ExtendClassComponent />)).toBe(true);\n      expect(isVNode(<FunctionalComponent />)).toBe(true);\n      expect(isVNode(<div />)).toBe(true);\n    });\n\n    it('should return false for non-VNodes', () => {\n      expect(isVNode(ClassComponent)).toBe(false);\n      expect(isVNode(ExtendClassComponent)).toBe(false);\n      expect(isVNode(FunctionalComponent)).toBe(false);\n      expect(isVNode(createDOMElement('div'))).toBe(false);\n      expect(isVNode('foo')).toBe(false);\n      expect(isVNode({})).toBe(false);\n      expect(isVNode([])).toBe(false);\n      expect(isVNode(10)).toBe(false);\n      expect(isVNode(undefined)).toBe(false);\n      expect(isVNode(null)).toBe(false);\n    });\n  });\n\n  describe('isComponentVNodeOfType', () => {\n    it('Should return true if Component is same', () => {\n      class Foobar extends Component {\n        render() {\n          return <div>1</div>;\n        }\n      }\n\n      expect(isComponentVNodeOfType(<Foobar />, Foobar)).toBe(true);\n      expect(isComponentVNodeOfType(<div />, Foobar)).toBe(false);\n    });\n  });\n\n  describe('isVNodeOfType', () => {\n    it('should return true for VNodes with a specified type', () => {\n      expect(isVNodeOfType(createElement('div'), 'div')).toBe(true);\n      expect(\n        isVNodeOfType(createElement(FunctionalComponent), FunctionalComponent),\n      ).toBe(true);\n      expect(isVNodeOfType(createElement(ClassComponent), ClassComponent)).toBe(\n        true,\n      );\n      expect(\n        isVNodeOfType(\n          createElement(ExtendClassComponent),\n          ExtendClassComponent,\n        ),\n      ).toBe(true);\n    });\n\n    it('should return false for VNodes with a specified type', () => {\n      expect(isVNodeOfType(createElement('div'), 'h1')).toBe(false);\n      expect(\n        isVNodeOfType(createElement(FunctionalComponent), ClassComponent),\n      ).toBe(false);\n      expect(\n        isVNodeOfType(createElement(ClassComponent), ExtendClassComponent),\n      ).toBe(false);\n      expect(\n        isVNodeOfType(createElement(ExtendClassComponent), FunctionalComponent),\n      ).toBe(false);\n    });\n  });\n\n  describe('isDOMVNode', () => {\n    it('should return true for VNodes of type string', () => {\n      expect(isDOMVNode(createElement('div'))).toBe(true);\n      expect(isDOMVNode(createElement('h1'))).toBe(true);\n      expect(isDOMVNode(createElement('p'))).toBe(true);\n    });\n\n    it('should return false for VNodes of type function or class', () => {\n      expect(isDOMVNode(createElement(ClassComponent))).toBe(false);\n      expect(isDOMVNode(createElement(ExtendClassComponent))).toBe(false);\n      expect(isDOMVNode(createElement(FunctionalComponent))).toBe(false);\n    });\n  });\n\n  describe('isDOMVNodeOfType', () => {\n    it('should return true for VNodes of specific string type', () => {\n      expect(isDOMVNodeOfType(createElement('div'), 'div')).toBe(true);\n      expect(isDOMVNodeOfType(createElement('h1'), 'h1')).toBe(true);\n      expect(isDOMVNodeOfType(createElement('p'), 'p')).toBe(true);\n    });\n\n    it('should return false for VNodes of incorrect type', () => {\n      expect(isDOMVNodeOfType(createElement('div'), 'foo')).toBe(false);\n      expect(isDOMVNodeOfType(createElement('div'), {} as never)).toBe(false);\n      expect(isDOMVNodeOfType(createElement('div'), [] as never)).toBe(false);\n      expect(isDOMVNodeOfType(createElement('div'), 10 as never)).toBe(false);\n      expect(isDOMVNodeOfType(createElement('div'), undefined as never)).toBe(\n        false,\n      );\n      expect(isDOMVNodeOfType(createElement('div'), null as never)).toBe(false);\n    });\n  });\n\n  describe('isFunctionalVNode', () => {\n    it('should return true for VNodes of stateless function type', () => {\n      expect(isFunctionalVNode(createElement(FunctionalComponent))).toBe(true);\n    });\n\n    it('should return false for VNodes of incorrect type', () => {\n      expect(isFunctionalVNode(createElement(ClassComponent))).toBe(false);\n      expect(isFunctionalVNode(createElement(ExtendClassComponent))).toBe(\n        false,\n      );\n      expect(isFunctionalVNode(createElement('div'))).toBe(false);\n    });\n  });\n\n  describe('isFunctionalVNodeOfType', () => {\n    it('should return true for VNodes of specific stateless function type', () => {\n      expect(\n        isFunctionalVNodeOfType(\n          createElement(FunctionalComponent),\n          FunctionalComponent,\n        ),\n      ).toBe(true);\n    });\n\n    it('should return false for VNodes of incorrect type', () => {\n      expect(\n        isFunctionalVNodeOfType(\n          createElement(FunctionalComponent),\n          AnotherFunctionalComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isFunctionalVNodeOfType(\n          createElement(FunctionalComponent),\n          ClassComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isFunctionalVNodeOfType(\n          createElement(FunctionalComponent),\n          ExtendClassComponent,\n        ),\n      ).toBe(false);\n    });\n  });\n\n  describe('isClassVNode', () => {\n    it('should return true for VNodes of class type', () => {\n      expect(isClassVNode(createElement(ClassComponent))).toBe(true);\n      expect(isClassVNode(createElement(ExtendClassComponent))).toBe(true);\n    });\n\n    it('should return false for VNodes of incorrect type', () => {\n      expect(isClassVNode(createElement(FunctionalComponent))).toBe(false);\n      expect(isClassVNode(createElement('div'))).toBe(false);\n    });\n  });\n\n  describe('isClassVNodeOfType', () => {\n    it('should return true for VNodes of specific class type', () => {\n      expect(\n        isClassVNodeOfType(createElement(ClassComponent), ClassComponent),\n      ).toBe(true);\n      expect(\n        isClassVNodeOfType(\n          createElement(ExtendClassComponent),\n          ExtendClassComponent,\n        ),\n      ).toBe(true);\n    });\n\n    it('should return false for VNodes of incorrect type', () => {\n      expect(\n        isClassVNodeOfType(\n          createElement(ClassComponent),\n          AnotherClassComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isClassVNodeOfType(\n          createElement(ClassComponent),\n          AnotherExtendClassComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isClassVNodeOfType(createElement(ClassComponent), FunctionalComponent),\n      ).toBe(false);\n\n      expect(\n        isClassVNodeOfType(\n          createElement(ExtendClassComponent),\n          AnotherClassComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isClassVNodeOfType(\n          createElement(ExtendClassComponent),\n          AnotherExtendClassComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isClassVNodeOfType(\n          createElement(ExtendClassComponent),\n          FunctionalComponent,\n        ),\n      ).toBe(false);\n    });\n  });\n\n  describe('isDOMElement', () => {\n    it('should return true for DOMElements', () => {\n      expect(isDOMElement(createDOMElement('div'))).toBe(true);\n      expect(isDOMElement(createDOMElement('h1'))).toBe(true);\n      expect(isDOMElement(createDOMElement('p'))).toBe(true);\n    });\n\n    it('should return false for non-DOMElements', () => {\n      expect(isDOMElement(createElement(ClassComponent))).toBe(false);\n      expect(isDOMElement(createElement(ExtendClassComponent))).toBe(false);\n      expect(isDOMElement(createElement(FunctionalComponent))).toBe(false);\n      expect(isDOMElement(createElement('div'))).toBe(false);\n      expect(isDOMElement(ClassComponent)).toBe(false);\n      expect(isDOMElement(ExtendClassComponent)).toBe(false);\n      expect(isDOMElement(FunctionalComponent)).toBe(false);\n      expect(isDOMElement('div')).toBe(false);\n      expect(isDOMElement(undefined)).toBe(false);\n      expect(isDOMElement(null)).toBe(false);\n      expect(isDOMElement({})).toBe(false);\n      expect(isDOMElement([])).toBe(false);\n      expect(isDOMElement(10)).toBe(false);\n    });\n  });\n\n  describe('isDOMElementOfType', () => {\n    it('should return true for DOMElements of specific type', () => {\n      expect(isDOMElementOfType(createDOMElement('div'), 'div')).toBe(true);\n      expect(isDOMElementOfType(createDOMElement('div'), 'DIV')).toBe(true);\n      expect(isDOMElementOfType(createDOMElement('h1'), 'h1')).toBe(true);\n      expect(isDOMElementOfType(createDOMElement('h1'), 'H1')).toBe(true);\n      expect(isDOMElementOfType(createDOMElement('p'), 'p')).toBe(true);\n      expect(isDOMElementOfType(createDOMElement('p'), 'P')).toBe(true);\n    });\n\n    it('should return false for DOMElements of incorrect type', () => {\n      expect(isDOMElementOfType(createDOMElement('div'), 'foo')).toBe(false);\n      expect(isDOMElementOfType(createDOMElement('div'), {} as never)).toBe(\n        false,\n      );\n      expect(isDOMElementOfType(createDOMElement('div'), [] as never)).toBe(\n        false,\n      );\n      expect(isDOMElementOfType(createDOMElement('div'), 10 as never)).toBe(\n        false,\n      );\n      expect(\n        isDOMElementOfType(createDOMElement('div'), undefined as never),\n      ).toBe(false);\n      expect(isDOMElementOfType(createDOMElement('div'), null as never)).toBe(\n        false,\n      );\n    });\n  });\n\n  describe('isRenderedClassComponent', () => {\n    const DOMVNode = createElement('div');\n    const functionalVNode = createElement(FunctionalComponent);\n    const createClassVNode = createElement(ClassComponent);\n    const extendClassVNode = createElement(ExtendClassComponent);\n\n    it('should return true for rendered Class Components', () => {\n      expect(\n        isRenderedClassComponent(renderIntoContainer(createClassVNode)),\n      ).toBe(true);\n      expect(\n        isRenderedClassComponent(renderIntoContainer(extendClassVNode)),\n      ).toBe(true);\n    });\n\n    it('should return false for non-rendered Class Components', () => {\n      expect(isRenderedClassComponent(createClassVNode)).toBe(false);\n      expect(isRenderedClassComponent(extendClassVNode)).toBe(false);\n      expect(\n        isRenderedClassComponent(renderIntoContainer(functionalVNode)),\n      ).toBe(false);\n      expect(isRenderedClassComponent(renderIntoContainer(DOMVNode))).toBe(\n        false,\n      );\n    });\n  });\n\n  describe('isRenderedClassComponentOfType', () => {\n    const createClassVNode = createElement(ClassComponent);\n    const extendClassVNode = createElement(ExtendClassComponent);\n\n    it('should return true for rendered Class Components of specific type', () => {\n      expect(\n        isRenderedClassComponentOfType(\n          renderIntoContainer(createClassVNode),\n          ClassComponent,\n        ),\n      ).toBe(true);\n      expect(\n        isRenderedClassComponentOfType(\n          renderIntoContainer(extendClassVNode),\n          ExtendClassComponent,\n        ),\n      ).toBe(true);\n    });\n\n    it('should return false for rendered Class Components of incorrect type', () => {\n      expect(\n        isRenderedClassComponentOfType(\n          renderIntoContainer(createClassVNode),\n          AnotherClassComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isRenderedClassComponentOfType(\n          renderIntoContainer(createClassVNode),\n          ExtendClassComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isRenderedClassComponentOfType(\n          renderIntoContainer(createClassVNode),\n          FunctionalComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isRenderedClassComponentOfType(\n          renderIntoContainer(createClassVNode),\n          'div' as never,\n        ),\n      ).toBe(false);\n\n      expect(\n        isRenderedClassComponentOfType(\n          renderIntoContainer(extendClassVNode),\n          AnotherExtendClassComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isRenderedClassComponentOfType(\n          renderIntoContainer(extendClassVNode),\n          ClassComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isRenderedClassComponentOfType(\n          renderIntoContainer(extendClassVNode),\n          FunctionalComponent,\n        ),\n      ).toBe(false);\n      expect(\n        isRenderedClassComponentOfType(\n          renderIntoContainer(extendClassVNode),\n          'div' as never,\n        ),\n      ).toBe(false);\n    });\n  });\n\n  describe('findAllInRenderedTree', () => {\n    let tree1;\n\n    beforeEach(() => {\n      tree1 = (\n        <section className=\"outer\">\n          <FunctionalComponent />\n        </section>\n      );\n      render(tree1, container);\n    });\n\n    it('should call predicate for each VNode instance in a rendered tree', () => {\n      const spy = jasmine.createSpy('spy');\n      expect(spy).not.toHaveBeenCalled();\n      findAllInRenderedTree(tree1, (args) => {\n        spy(args.type);\n\n        return true;\n      });\n      // 0: section\n      // 1: FunctionalComponent\n      // 2: div\n      expect(spy).toHaveBeenCalledTimes(3);\n      expect(spy).toHaveBeenCalledWith('section');\n      expect(spy).toHaveBeenCalledWith(FunctionalComponent);\n      expect(spy).toHaveBeenCalledWith('div');\n    });\n\n    it('should call predicate in the correct order', () => {\n      const types: unknown[] = [];\n      findAllInRenderedTree(tree1, ({ type }) => {\n        types.push(type);\n        return true;\n      });\n      expect(types).toEqual(['section', FunctionalComponent, 'div']);\n    });\n\n    it('should work with interpolated text', () => {\n      const predicate = jasmine.createSpy('spy');\n      const Hello = ({ who }) => <div>Hello, {who}!</div>;\n      const tree = <Hello who=\"world\" />;\n      render(tree, container);\n      expect(predicate).not.toHaveBeenCalled();\n      findAllInRenderedTree(tree, predicate);\n\n      expect(predicate).toHaveBeenCalledTimes(5);\n    });\n\n    it('should work without class wrappers', () => {\n      const predicate = jasmine.createSpy('spy');\n      const Hello = ({ who }) => <div>Hello, {who}!</div>;\n      const treeWithText = <Hello who=\"world\" />;\n      render(treeWithText, container);\n\n      expect(predicate).not.toHaveBeenCalled();\n      findAllInRenderedTree(treeWithText, predicate);\n\n      expect(predicate).toHaveBeenCalledTimes(5);\n    });\n  });\n\n  describe('findAllInVNodeTree', () => {\n    const tree2 = (\n      <section className=\"outer\">\n        <FunctionalComponent />\n      </section>\n    );\n\n    it('should throw an error when not passed a VNode', () => {\n      const predicate = () => {\n        return true;\n      };\n      const testValue = (value) => {\n        expect(() => {\n          findAllInVNodeTree(value, predicate);\n        }).toThrow();\n      };\n      testValue(render(<div />, container));\n      testValue(ClassComponent);\n      testValue(ExtendClassComponent);\n      testValue(FunctionalComponent);\n      testValue(createDOMElement('div'));\n      testValue(undefined);\n      testValue(null);\n      testValue('foo');\n      testValue({});\n      testValue([]);\n      testValue(10);\n    });\n\n    it('should call predicate for each VNode instance in an non-rendered tree', () => {\n      const predicate = jasmine.createSpy('spy');\n\n      findAllInVNodeTree(tree2, (args) => {\n        predicate(args.type);\n        return true;\n      });\n      // 0: section\n      // 1: FunctionalComponent\n      expect(predicate).toHaveBeenCalledTimes(2);\n      expect(predicate).toHaveBeenCalledWith('section');\n      expect(predicate).toHaveBeenCalledWith(FunctionalComponent);\n    });\n\n    it('should call predicate in the correct order', () => {\n      const types: unknown[] = [];\n      findAllInVNodeTree(tree2, ({ type }) => {\n        types.push(type);\n        return true;\n      });\n      expect(types).toEqual(['section', FunctionalComponent]);\n    });\n  });\n\n  describe('scryRenderedDOMElementsWithClass', () => {\n    const tree3 = renderIntoContainer(\n      <div className=\"level-1 one\">\n        <div className=\"level-2 one\">\n          <div className=\"level-3 one\" />\n        </div>\n        <div className=\"level-2 two\">\n          <span className=\"level-3 two\" />\n        </div>\n      </div>,\n    );\n\n    it('should return an array of matched DOM elements', () => {\n      const result1 = scryRenderedDOMElementsWithClass(tree3, 'one');\n      expect(result1 instanceof Array).toBeTruthy();\n      expect(result1.length).toBe(3);\n      for (const result of result1) {\n        expect(result.tagName).toBe('DIV');\n      }\n\n      const result2 = scryRenderedDOMElementsWithClass(tree3, 'two');\n      expect(result2 instanceof Array).toBeTruthy();\n      expect(result2.length).toBe(2);\n      expect(result2[0].tagName).toBe('DIV');\n      expect(result2[1].tagName).toBe('SPAN');\n\n      const result3 = scryRenderedDOMElementsWithClass(tree3, 'three');\n      expect(result3 instanceof Array).toBeTruthy();\n      expect(result3.length).toBe(0);\n    });\n\n    it('should accept a space separated string of class names', () => {\n      const result1 = scryRenderedDOMElementsWithClass(tree3, 'level-2');\n      expect(result1 instanceof Array).toBeTruthy();\n      expect(result1.length).toBe(2);\n\n      const result2 = scryRenderedDOMElementsWithClass(tree3, 'level-2 one');\n      expect(result2 instanceof Array).toBeTruthy();\n      expect(result2.length).toBe(1);\n    });\n\n    it('should accept an array of class names', () => {\n      const result = scryRenderedDOMElementsWithClass(tree3, [\n        'level-2',\n        'one',\n      ]);\n      expect(result instanceof Array).toBeTruthy();\n      expect(result.length).toBe(1);\n    });\n  });\n\n  describe('scryRenderedDOMElementsWithTag', () => {\n    const tree4 = renderIntoContainer(\n      <div>\n        <header>\n          <h1>Hello</h1>\n        </header>\n        <section>\n          <h1>Hello Again</h1>\n          <p>Paragraph 1</p>\n          <p>Paragraph 2</p>\n          <p>Paragraph 3</p>\n        </section>\n      </div>,\n    );\n\n    it('should return an array of matched DOM elements', () => {\n      const testValue = (tagName, length) => {\n        const result = scryRenderedDOMElementsWithTag(tree4, tagName);\n        expect(result instanceof Array).toBeTruthy();\n        expect(result.length).toBe(length);\n        for (const item of result) {\n          expect(item.tagName).toBe(tagName.toUpperCase());\n        }\n      };\n      testValue('div', 1);\n      testValue('h1', 2);\n      testValue('p', 3);\n      testValue('span', 0);\n    });\n  });\n\n  describe('scryRenderedVNodesWithType', () => {\n    const tree5 = renderIntoContainer(\n      <div>\n        <FunctionalComponent />\n        <FunctionalComponent />\n        <ClassComponent />\n        <ClassComponent />\n        <ExtendClassComponent />\n        <ExtendClassComponent />\n      </div>,\n    );\n\n    it('should return an array of matched VNodes', () => {\n      const testValue = (type, length) => {\n        const result = scryRenderedVNodesWithType(tree5, type);\n        expect(result instanceof Array).toBeTruthy();\n        expect(result.length).toBe(length);\n        for (const item of result) {\n          expect(item instanceof Object).toBeTruthy();\n          expect(Object.keys(item).sort()).toEqual(VNodeKeys);\n          expect(isVNode(item)).toBe(true);\n        }\n      };\n      testValue('p', 0);\n      testValue('div', 7); // Outer div + each rendered component div\n      testValue(FunctionalComponent, 2);\n      testValue(ClassComponent, 2);\n      testValue(ExtendClassComponent, 2);\n      testValue(AnotherFunctionalComponent, 0);\n    });\n  });\n\n  describe('scryVNodesWithType', () => {\n    const tree6 = (\n      <div>\n        <FunctionalComponent />\n        <FunctionalComponent />\n        <ClassComponent />\n        <ClassComponent />\n        <ExtendClassComponent />\n        <ExtendClassComponent />\n      </div>\n    );\n\n    it('should return an array of matched VNodes', () => {\n      const testValue = (type, length) => {\n        const result = scryVNodesWithType(tree6, type);\n        expect(result instanceof Array).toBeTruthy();\n        expect(result.length).toBe(length);\n        for (const item of result) {\n          expect(item instanceof Object).toBeTruthy();\n          expect(Object.keys(item).sort()).toEqual(VNodeKeys);\n          expect(isVNode(item)).toBe(true);\n        }\n      };\n      testValue('p', 0);\n      testValue('div', 1); // Just the outer div\n      testValue(FunctionalComponent, 2);\n      testValue(ClassComponent, 2);\n      testValue(ExtendClassComponent, 2);\n      testValue(AnotherFunctionalComponent, 0);\n    });\n  });\n\n  describe('findRenderedDOMElementWithClass', () => {\n    const tree7 = renderIntoContainer(\n      <div className=\"level-1 one\">\n        <div className=\"level-2 one\">\n          <div className=\"level-3 one\" />\n        </div>\n        <div className=\"level-2 two\">\n          <span className=\"level-3 two\" />\n        </div>\n      </div>,\n    );\n\n    it('should throw an error when more than one result is found #1', () => {\n      const testValue = (classNames) => {\n        expect(() => {\n          findRenderedDOMElementWithClass(tree7, classNames);\n        }).toThrow();\n      };\n      testValue('level-2');\n      testValue('level-3');\n    });\n\n    it('should return a matched DOM element', () => {\n      const testValue = (classNames) => {\n        const result = findRenderedDOMElementWithClass(tree7, classNames);\n        const arrOfClassName = classNames.split(' ');\n        for (let i = 0; i < arrOfClassName.length; i++) {\n          expect(result.classList.contains(arrOfClassName[i])).toBe(true);\n        }\n      };\n      testValue('level-1');\n      testValue('level-2 one');\n      testValue('level-3 two');\n    });\n\n    it('should be able to handle null elements', () => {\n      const NoOp = () => null;\n      const Broken = () => (\n        <div className=\"dummy\">\n          <NoOp />\n        </div>\n      );\n      const renderedTree = renderIntoContainer(<Broken />);\n      const dummy = findRenderedDOMElementWithClass(renderedTree, 'dummy');\n      expect(dummy.className).toBe('dummy');\n    });\n  });\n\n  describe('findRenderedDOMElementWithTag', () => {\n    const tree8 = renderIntoContainer(\n      <div>\n        <header>\n          <h1>Head1</h1>\n          <span>Hello</span>\n        </header>\n        <section>\n          <h1>Hello Again</h1>\n          <p>Paragraph 1</p>\n          <p>Paragraph 2</p>\n          <p>Paragraph 3</p>\n          <a>test</a>\n        </section>\n      </div>,\n    );\n\n    it('should throw an error when more than one result is found #2', () => {\n      const testValue = (tagName) => {\n        expect(() => {\n          findRenderedDOMElementWithTag(tree8, tagName);\n        }).toThrow();\n      };\n      testValue('h1');\n      testValue('p');\n    });\n\n    it('should return a matched DOM element', () => {\n      const testValue = (tagName) => {\n        const result = findRenderedDOMElementWithTag(tree8, tagName);\n\n        expect(result.tagName).toBe(tagName.toUpperCase());\n      };\n      testValue('div');\n      testValue('span');\n      testValue('a');\n    });\n  });\n\n  describe('findRenderedVNodeWithType', () => {\n    const tree9 = renderIntoContainer(\n      <div>\n        <h1>Hello</h1>\n        <FunctionalComponent />\n        <FunctionalComponent />\n        <ClassComponent />\n        <ExtendClassComponent />\n      </div>,\n    );\n\n    it('should throw an error when more than one result is found #3', () => {\n      const testValue = (type) => {\n        expect(() => {\n          findRenderedVNodeWithType(tree9, type);\n        }).toThrow();\n      };\n      testValue('div');\n      testValue(FunctionalComponent);\n    });\n\n    it('should return a matched VNode #1', () => {\n      const testValue = (type) => {\n        const result = findRenderedVNodeWithType(tree9, type);\n        expect(result instanceof Object).toBeTruthy();\n        expect(Object.keys(result).sort()).toEqual(VNodeKeys);\n        expect(isVNode(result)).toBe(true);\n        expect(result.type).toBe(type);\n      };\n      testValue('h1');\n      testValue(ClassComponent);\n      testValue(ExtendClassComponent);\n    });\n  });\n\n  describe('findVNodeWithType', () => {\n    const tree10 = (\n      <div>\n        <div>\n          <h1>Hello</h1>\n        </div>\n        <FunctionalComponent />\n        <FunctionalComponent />\n        <ClassComponent />\n        <ExtendClassComponent />\n      </div>\n    );\n\n    it('should throw an error when more than one result is found #4', () => {\n      const testValue = (type) => {\n        expect(() => {\n          findVNodeWithType(tree10, type);\n        }).toThrow();\n      };\n      testValue('div');\n      testValue(FunctionalComponent);\n    });\n\n    it('should return a matched VNode #2', () => {\n      const testValue = (type) => {\n        const result = findVNodeWithType(tree10, type);\n        expect(result instanceof Object).toBeTruthy();\n        expect(Object.keys(result).sort()).toEqual(VNodeKeys);\n        expect(isVNode(result)).toBe(true);\n        expect(result.type).toBe(type);\n      };\n      testValue('h1');\n      testValue(ClassComponent);\n      testValue(ExtendClassComponent);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-test-utils/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-test-utils/package.json",
    "content": "{\n  \"name\": \"inferno-test-utils\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"description\": \"Suite of utilities for testing Inferno applications\",\n  \"author\": {\n    \"name\": \"Matthew Wagerfield\",\n    \"email\": \"matthew@wagerfield.com\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"keywords\": [\n    \"babel\",\n    \"react\",\n    \"inferno\",\n    \"framework\",\n    \"interfaces\",\n    \"tests\",\n    \"utils\"\n  ],\n  \"devDependencies\": {\n    \"inferno-shared\": \"9.0.11\",\n    \"inferno-vnode-flags\": \"9.0.11\"\n  },\n  \"dependencies\": {\n    \"inferno\": \"9.0.11\"\n  },\n  \"rollup\": {\n    \"bundledDependencies\": [\n      \"inferno-shared\",\n      \"inferno-vnode-flags\"\n    ],\n    \"moduleName\": \"Inferno.TestUtils\",\n    \"moduleGlobals\": {\n      \"inferno\": \"Inferno\"\n    }\n  },\n  \"files\": [\n    \"index.cjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-test-utils\"\n  }\n}\n"
  },
  {
    "path": "packages/inferno-test-utils/src/index.ts",
    "content": "import {\n  type Component,\n  render,\n  type VNode,\n  type InfernoChild,\n  type InfernoFragment,\n  type Inferno,\n} from 'inferno';\nimport {\n  isArray,\n  isFunction,\n  isInvalid,\n  isNullOrUndef,\n  isString,\n  throwError,\n} from 'inferno-shared';\nimport {\n  getTagNameOfVNode as _getTagNameOfVNode,\n  isClassVNode as _isClassVNode,\n  isComponentVNode as _isComponentVNode,\n  isDOMVNode as _isDOMVNode,\n  isFunctionalVNode as _isFunctionalVNode,\n  isTextVNode as _isTextVNode,\n  isVNode as _isVNode,\n  Wrapper as _Wrapper,\n} from './utils';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport {\n  renderToSnapshot as _renderToSnapshot,\n  vNodeToSnapshot as _vNodeToSnapshot,\n} from './jest';\n\n// Type Checkers\n\nexport function isVNodeOfType(obj: VNode, type: unknown): boolean {\n  return _isVNode(obj) && obj.type === type;\n}\n\nexport function isDOMVNodeOfType(obj: VNode, type: string): boolean {\n  return _isDOMVNode(obj) && obj.type === type;\n}\n\nexport function isFunctionalVNodeOfType(obj: VNode, type: Function): boolean {\n  return _isFunctionalVNode(obj) && obj.type === type;\n}\n\nexport function isClassVNodeOfType(\n  obj: VNode,\n  type: Inferno.ComponentClass<unknown> | Inferno.StatelessComponent<unknown>,\n): boolean {\n  return _isClassVNode(obj) && obj.type === type;\n}\n\nexport function isComponentVNodeOfType(obj: VNode, type: Function): boolean {\n  return (_isFunctionalVNode(obj) || _isClassVNode(obj)) && obj.type === type;\n}\n\nexport function isDOMElement(obj: any): boolean {\n  return (\n    Boolean(obj) &&\n    typeof obj === 'object' &&\n    obj.nodeType === 1 &&\n    isString(obj.tagName)\n  );\n}\n\nexport function isDOMElementOfType(obj: any, type: string): boolean {\n  return (\n    isDOMElement(obj) &&\n    isString(type) &&\n    obj.tagName.toLowerCase() === type.toLowerCase()\n  );\n}\n\nexport function isRenderedClassComponent(obj: any): boolean {\n  return (\n    Boolean(obj) &&\n    typeof obj === 'object' &&\n    _isVNode(obj.$LI) &&\n    isFunction(obj.render) &&\n    isFunction(obj.setState)\n  );\n}\n\nexport function isRenderedClassComponentOfType(\n  obj: any,\n  type: Inferno.ComponentClass<unknown> | Inferno.StatelessComponent<unknown>,\n): boolean {\n  return (\n    isRenderedClassComponent(obj) &&\n    isFunction(type) &&\n    obj.constructor === type\n  );\n}\n\n// Recursive Finder Functions\n\nexport function findAllInRenderedTree(\n  renderedTree: any,\n  predicate: (vNode: VNode) => boolean,\n): VNode[] | any {\n  if (isRenderedClassComponent(renderedTree)) {\n    return findAllInVNodeTree(renderedTree.$LI, predicate);\n  } else {\n    return findAllInVNodeTree(renderedTree, predicate);\n  }\n}\n\nexport function findAllInVNodeTree(\n  vNodeTree: VNode,\n  predicate: (vNode: VNode) => boolean,\n): any {\n  if (_isVNode(vNodeTree)) {\n    let result: VNode[] = predicate(vNodeTree) ? [vNodeTree] : [];\n    const children: any = vNodeTree.children;\n\n    if (isRenderedClassComponent(children)) {\n      result = result.concat(\n        findAllInVNodeTree(children.$LI, predicate) as VNode[],\n      );\n    } else if (_isVNode(children)) {\n      result = result.concat(\n        findAllInVNodeTree(children, predicate) as VNode[],\n      );\n    } else if (isArray(children)) {\n      for (const child of children) {\n        if (!isInvalid(child)) {\n          result = result.concat(\n            findAllInVNodeTree(child, predicate) as VNode[],\n          );\n        }\n      }\n    }\n    return result;\n  } else {\n    throwError(\n      'findAllInVNodeTree(vNodeTree, predicate) vNodeTree must be a VNode instance',\n    );\n  }\n}\n\n// Finder Helpers\n\nfunction parseSelector(filter: unknown): unknown[] {\n  if (isArray(filter)) {\n    return filter;\n  } else if (isString(filter)) {\n    return filter.trim().split(/\\s+/);\n  } else {\n    return [];\n  }\n}\n\nfunction findOneOf<TResult, TArgTree, TArgFilter>(\n  tree: TArgTree,\n  filter: TArgFilter,\n  name: string,\n  finder: (renderedTree: TArgTree, type: TArgFilter) => TResult[],\n): TResult {\n  const all = finder(tree, filter);\n  if (all.length > 1) {\n    throwError(\n      `Did not find exactly one match (found ${all.length}) for ${name}: ${filter}`,\n    );\n  }\n  return all[0];\n}\n\n// Scry Utilities\n\nexport function scryRenderedDOMElementsWithClass(\n  renderedTree: any,\n  classNames: string | string[],\n): Element[] {\n  return findAllInRenderedTree(renderedTree, (instance) => {\n    if (_isDOMVNode(instance)) {\n      let domClassName = !isNullOrUndef(instance.dom)\n        ? instance.dom.className\n        : '';\n\n      if (\n        !isString(domClassName) &&\n        !isNullOrUndef(instance.dom) &&\n        isFunction(instance.dom.getAttribute)\n      ) {\n        // SVG || null, probably\n        domClassName = instance.dom.getAttribute('class') || '';\n      }\n\n      const domClassList = parseSelector(domClassName);\n      return parseSelector(classNames).every((className) => {\n        return domClassList.includes(className);\n      });\n    }\n    return false;\n  }).map((instance) => instance.dom);\n}\n\nexport function scryRenderedDOMElementsWithTag(\n  renderedTree: any,\n  tagName: string,\n): Element[] {\n  return findAllInRenderedTree(renderedTree, (instance) => {\n    return isDOMVNodeOfType(instance, tagName);\n  }).map((instance) => instance.dom);\n}\n\nexport function scryRenderedVNodesWithType(\n  renderedTree: any,\n  type: unknown,\n): VNode[] {\n  return findAllInRenderedTree(renderedTree, (instance) =>\n    isVNodeOfType(instance, type),\n  );\n}\n\nexport function scryVNodesWithType(vNodeTree: VNode, type: unknown): VNode[] {\n  return findAllInVNodeTree(vNodeTree, (instance) =>\n    isVNodeOfType(instance, type),\n  );\n}\n\n// Find Utilities\n\nexport function findRenderedDOMElementWithClass(\n  renderedTree: any,\n  classNames: string | string[],\n): Element {\n  return findOneOf(\n    renderedTree,\n    classNames,\n    'class',\n    scryRenderedDOMElementsWithClass,\n  );\n}\n\nexport function findRenderedDOMElementWithTag(\n  renderedTree: any,\n  tagName: string,\n): Element {\n  return findOneOf(\n    renderedTree,\n    tagName,\n    'tag',\n    scryRenderedDOMElementsWithTag,\n  );\n}\n\nexport function findRenderedVNodeWithType(\n  renderedTree: any,\n  type: unknown,\n): VNode {\n  return findOneOf(renderedTree, type, 'component', scryRenderedVNodesWithType);\n}\n\nexport function findVNodeWithType(vNodeTree: VNode, type: unknown): VNode {\n  return findOneOf(vNodeTree, type, 'VNode', scryVNodesWithType);\n}\n\nexport function renderIntoContainer(\n  input: boolean | VNode | InfernoChild | InfernoFragment | null | undefined,\n): Component<any, any> | VNode {\n  const container: any = document.createElement('div');\n\n  render(input, container);\n\n  const rootInput = container.$V;\n\n  if (rootInput && rootInput.flags & VNodeFlags.Component) {\n    return rootInput.children;\n  }\n\n  return rootInput;\n}\n\nexport const vNodeToSnapshot = _vNodeToSnapshot;\nexport const renderToSnapshot = _renderToSnapshot;\nexport const getTagNameOfVNode = _getTagNameOfVNode;\nexport const isClassVNode = _isClassVNode;\nexport const isComponentVNode = _isComponentVNode;\nexport const isDOMVNode = _isDOMVNode;\nexport const isFunctionalVNode = _isFunctionalVNode;\nexport const isTextVNode = _isTextVNode;\nexport const isVNode = _isVNode;\nexport const Wrapper = _Wrapper;\n"
  },
  {
    "path": "packages/inferno-test-utils/src/jest.ts",
    "content": "import { render, rerender, type VNode } from 'inferno';\nimport { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';\nimport { isArray, isNullOrUndef } from 'inferno-shared';\nimport { getTagNameOfVNode } from './utils';\n\n// Jest Snapshot Utilities\n// Jest formats its snapshots prettily because it knows how to play with the React test renderer.\n// Symbols and algorithm have been reversed from the following file:\n// https://github.com/facebook/react/blob/v15.4.2/src/renderers/testing/ReactTestRenderer.js#L98\n\ntype InfernoTestRendererNode = InfernoSnapshot | string;\n\nexport interface InfernoSnapshot {\n  type: string;\n  props: Record<string, any>;\n  children: null | InfernoTestRendererNode[];\n  $$typeof?: symbol | string;\n}\n\nconst symbolValue =\n  typeof Symbol === 'undefined'\n    ? 'react.test.json'\n    : Symbol.for('react.test.json');\n\nfunction createSnapshotObject(object: InfernoSnapshot): InfernoSnapshot {\n  Object.defineProperty(object, '$$typeof', {\n    value: symbolValue,\n  });\n\n  return object;\n}\n\nfunction removeChildren(item): void {\n  if (Array.isArray(item)) {\n    for (let i = 0; i < item.length; ++i) {\n      removeChildren(item[i]);\n    }\n  } else if (item?.props) {\n    if (Object.prototype.hasOwnProperty.call(item.props, 'children')) {\n      delete item.props.children;\n    }\n\n    removeChildren(item.children);\n  }\n}\n\nfunction buildVNodeSnapshot(vNode: VNode): InfernoSnapshot {\n  const flags = vNode.flags;\n  const children: any = vNode.children;\n  let childVNode;\n\n  if (flags & VNodeFlags.ComponentClass) {\n    childVNode = buildVNodeSnapshot(children.$LI);\n  } else if (flags & VNodeFlags.ComponentFunction) {\n    childVNode = buildVNodeSnapshot(children);\n  }\n\n  if (vNode.childFlags === ChildFlags.HasVNodeChildren) {\n    childVNode = buildVNodeSnapshot(children);\n  } else if (vNode.childFlags & ChildFlags.MultipleChildren) {\n    childVNode = [];\n\n    for (let i = 0, len = children.length; i < len; ++i) {\n      childVNode.push(buildVNodeSnapshot(children[i]));\n    }\n  } else if (vNode.childFlags & ChildFlags.HasTextChildren) {\n    childVNode = (vNode.children as string | number) + '';\n  }\n\n  if (flags & VNodeFlags.Element) {\n    const snapShotProps: any = {};\n    const props = vNode.props;\n\n    if (props) {\n      const keys = Object.keys(props);\n\n      for (let i = 0; i < keys.length; ++i) {\n        const key = keys[i];\n        const value = props[key];\n\n        if (value !== undefined) {\n          snapShotProps[key] = value;\n        }\n      }\n    }\n\n    if (!isNullOrUndef(vNode.className)) {\n      snapShotProps.className = vNode.className;\n    }\n\n    // Jest expects children to always be an array\n    if (childVNode && !isArray(childVNode)) {\n      childVNode = [childVNode];\n    }\n\n    return createSnapshotObject({\n      children: childVNode,\n      props: snapShotProps,\n      type: getTagNameOfVNode(vNode) as string,\n    });\n  } else if (flags & VNodeFlags.Text) {\n    childVNode = (vNode.children as string | number) + '';\n  }\n\n  return childVNode;\n}\n\nexport function vNodeToSnapshot(vNode: VNode): InfernoSnapshot {\n  return buildVNodeSnapshot(vNode);\n}\n\nexport function renderToSnapshot(input: VNode): InfernoSnapshot {\n  render(input, document.createElement('div'));\n  rerender(); // Flush all pending set state calls\n  const snapshot = vNodeToSnapshot(input);\n\n  removeChildren(snapshot);\n\n  return snapshot;\n}\n"
  },
  {
    "path": "packages/inferno-test-utils/src/utils.ts",
    "content": "import { Component, type InfernoNode, type VNode } from 'inferno';\nimport { VNodeFlags } from 'inferno-vnode-flags';\nimport { isNumber } from 'inferno-shared';\n\nexport function isVNode(obj: any): obj is VNode {\n  return (\n    Boolean(obj) &&\n    typeof obj === 'object' &&\n    isNumber(obj.flags) &&\n    obj.flags > 0\n  );\n}\n\nexport function isTextVNode(obj: VNode): obj is VNode {\n  return (obj.flags & VNodeFlags.Text) > 0;\n}\n\nexport function isFunctionalVNode(obj: VNode): obj is VNode {\n  return isVNode(obj) && (obj.flags & VNodeFlags.ComponentFunction) > 0;\n}\n\nexport function isClassVNode(obj: VNode): obj is VNode {\n  return isVNode(obj) && (obj.flags & VNodeFlags.ComponentClass) > 0;\n}\n\nexport function isComponentVNode(obj: VNode): obj is VNode {\n  return isFunctionalVNode(obj) || isClassVNode(obj);\n}\n\nexport function getTagNameOfVNode(vNode: VNode): string | undefined {\n  return vNode?.dom?.tagName.toLowerCase();\n}\n\nexport function isDOMVNode(vNode: any): vNode is VNode {\n  return (\n    !isComponentVNode(vNode) &&\n    !isTextVNode(vNode) &&\n    (vNode.flags & VNodeFlags.Element) > 0\n  );\n}\n\nexport class Wrapper<P, S> extends Component<P, S> {\n  public render(): InfernoNode {\n    return this.props.children;\n  }\n}\n"
  },
  {
    "path": "packages/inferno-utils/__tests__/utils.spec.tsx",
    "content": "import {\n  createContainerWithHTML,\n  triggerEvent,\n  validateNodeTree,\n} from 'inferno-utils';\n\ndescribe('Utils', () => {\n  describe('createContainerWithHTML', () => {\n    it('should create a container with the passed in HTML', () => {\n      const container = createContainerWithHTML('<h1>hello!</h1>');\n      expect(container.innerHTML).toBe('<h1>hello!</h1>');\n      expect(container.tagName).toBe('DIV');\n    });\n  });\n  describe('validateNodeTree', () => {\n    it('should return true if called with falsy arguments', () => {\n      expect(validateNodeTree(false)).toBe(true);\n      expect(validateNodeTree(null)).toBe(true);\n      expect(validateNodeTree(undefined)).toBe(true);\n    });\n\n    it('should return true if called with a string', () => {\n      expect(validateNodeTree('<div><h1>test</h1></div>')).toBe(true);\n    });\n\n    it('should return true if called with a number', () => {\n      expect(validateNodeTree(4)).toBe(true);\n    });\n  });\n\n  describe('triggerEvent', () => {\n    let expectedEventType = '';\n    const element = {\n      dispatchEvent() {},\n    };\n    let spyDispatch;\n    let spyCreateMouseEvent;\n    let triggerName;\n    let spyEvent;\n\n    beforeEach(function () {\n      spyDispatch = spyOn(element, 'dispatchEvent');\n\n      spyCreateMouseEvent = spyOn(document, 'createEvent').and.callFake(\n        (ev) => {\n          expect(ev).toBe(expectedEventType);\n\n          spyEvent = {\n            initEvent: (eventType, _canBubble, cancelable) => {\n              expect(eventType).toBe(triggerName);\n              // expect(canBubble).toBe(true);\n              expect(cancelable).toBe(true);\n            },\n          };\n\n          return spyEvent;\n        },\n      );\n    });\n\n    afterEach(function () {\n      spyDispatch.calls.reset();\n      spyCreateMouseEvent.calls.reset();\n    });\n\n    it('should trigger event on click', () => {\n      expectedEventType = 'MouseEvents';\n      triggerName = 'click';\n\n      triggerEvent(triggerName, element);\n\n      expect(spyDispatch.calls.argsFor(0)[0]).toBe(spyEvent);\n    });\n\n    it('should trigger event on dblclick', () => {\n      expectedEventType = 'MouseEvents';\n      triggerName = 'dblclick';\n\n      triggerEvent(triggerName, element);\n\n      expect(spyDispatch.calls.argsFor(0)[0]).toBe(spyEvent);\n    });\n\n    it('should trigger event on mousedown', () => {\n      expectedEventType = 'MouseEvents';\n      triggerName = 'mousedown';\n\n      triggerEvent(triggerName, element);\n\n      expect(spyDispatch.calls.argsFor(0)[0]).toBe(spyEvent);\n    });\n\n    it('should trigger event on mouseup', () => {\n      expectedEventType = 'MouseEvents';\n      triggerName = 'mouseup';\n\n      triggerEvent(triggerName, element);\n\n      expect(spyDispatch.calls.argsFor(0)[0]).toBe(spyEvent);\n    });\n\n    it('should trigger event on focus', () => {\n      expectedEventType = 'HTMLEvents';\n      triggerName = 'focus';\n\n      triggerEvent(triggerName, element);\n\n      expect(spyDispatch.calls.argsFor(0)[0]).toBe(spyEvent);\n    });\n\n    it('should trigger event on change', () => {\n      expectedEventType = 'HTMLEvents';\n      triggerName = 'change';\n\n      triggerEvent(triggerName, element);\n\n      expect(spyDispatch.calls.argsFor(0)[0]).toBe(spyEvent);\n    });\n\n    it('should trigger event on blur', () => {\n      expectedEventType = 'HTMLEvents';\n      triggerName = 'blur';\n\n      triggerEvent(triggerName, element);\n\n      expect(spyDispatch.calls.argsFor(0)[0]).toBe(spyEvent);\n    });\n\n    it('should trigger event on select', () => {\n      expectedEventType = 'HTMLEvents';\n      triggerName = 'select';\n\n      triggerEvent(triggerName, element);\n\n      expect(spyDispatch.calls.argsFor(0)[0]).toBe(spyEvent);\n    });\n\n    it('should throw an error on unknown event', () => {\n      expectedEventType = 'HTMLEvents';\n      triggerName = 'blah';\n\n      expect(triggerEvent.bind(triggerEvent, triggerName, element)).toThrow();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/inferno-utils/package.json",
    "content": "{\n  \"name\": \"inferno-utils\",\n  \"version\": \"9.0.11\",\n  \"description\": \"Meta test utilities which are not for userland\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-utils\"\n  },\n  \"devDependencies\": {\n    \"inferno-shared\": \"9.0.11\",\n    \"inferno-vnode-flags\": \"9.0.11\"\n  },\n  \"type\": \"module\",\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"private\": true\n}\n"
  },
  {
    "path": "packages/inferno-utils/src/index.ts",
    "content": "import { isArray, isNullOrUndef, isStringOrNumber } from 'inferno-shared';\nimport { VNodeFlags } from 'inferno-vnode-flags';\n\nexport function createContainerWithHTML(html: string): HTMLDivElement {\n  const container = document.createElement('div');\n\n  container.innerHTML = html;\n  return container;\n}\n\nexport function validateNodeTree(node: any): boolean {\n  if (!node) {\n    return true;\n  }\n  if (isStringOrNumber(node)) {\n    return true;\n  }\n  const children = node.children;\n  const flags = node.flags;\n\n  if ((flags & VNodeFlags.Element) > 0) {\n    if (!node.dom) {\n      return false;\n    }\n    if (!isNullOrUndef(children)) {\n      if (isArray(children)) {\n        for (let i = 0, len = children.length; i < len; i++) {\n          const val = validateNodeTree(children[i]);\n\n          if (!val) {\n            return false;\n          }\n        }\n      } else {\n        const val = validateNodeTree(children);\n\n        if (!val) {\n          return false;\n        }\n      }\n    }\n  }\n  return true;\n}\n\nexport function triggerEvent(name: string, element): void {\n  let eventType;\n\n  if (\n    name === 'click' ||\n    name === 'dblclick' ||\n    name === 'mousedown' ||\n    name === 'mouseup'\n  ) {\n    eventType = 'MouseEvents';\n  } else if (\n    name === 'focus' ||\n    name === 'change' ||\n    name === 'blur' ||\n    name === 'input' ||\n    name === 'select'\n  ) {\n    eventType = 'HTMLEvents';\n  } else {\n    throw new Error('Unsupported `\"' + name + '\"`event');\n  }\n  const event = document.createEvent(eventType);\n  if (eventType === 'MouseEvents') {\n    // Simulate left click always\n    Object.defineProperty(event, 'button', {\n      value: 0,\n    });\n  }\n  event.initEvent(name, name !== 'change', true);\n  element.dispatchEvent(event);\n}\n"
  },
  {
    "path": "packages/inferno-vnode-flags/README.md",
    "content": "# inferno-vnode-flags\n\nInferno VNode Flags is a small utility library for [Inferno](https://github.com/infernojs/inferno).\n\nUsage of `inferno-vnode-flags` should be limited to assigning `VNodeFlags` and `ChildFlags` when using creating vNodes.\n\n## Install\n\n```\nnpm install --save inferno-vnode-flags\n```\n\n## Contents\n\n**VNodeFlags:**\n\n- `VNodeFlags.HtmlElement`\n- `VNodeFlags.ComponentUnknown`\n- `VNodeFlags.ComponentClass`\n- `VNodeFlags.ComponentFunction`\n- `VNodeFlags.Text`\n- `VNodeFlags.SvgElement`\n- `VNodeFlags.InputElement`\n- `VNodeFlags.TextareaElement`\n- `VNodeFlags.SelectElement`\n- `VNodeFlags.Portal`\n- `VNodeFlags.ReCreate` (JSX **$ReCreate**) always re-creates the vNode\n- `VNodeFlags.ContentEditable`\n- `VNodeFlags.Fragment`\n- `VNodeFlags.InUse`\n- `VnodeFlags.ForwardRef`\n- `VNodeFlags.Normalized`\n\n**VNodeFlags Masks:**\n\n- `VNodeFlags.ForwardRefComponent` Functional component wrapped in forward ref\n- `VNodeFlags.FormElement` - Is form element\n- `VNodeFlags.Element` - Is vNode element\n- `VNodeFlags.Component` - Is vNode Component\n- `VNodeFlags.DOMRef` - Bit set when vNode holds DOM reference\n- `VNodeFlags.InUseOrNormalized` - VNode is used somewhere else or came from normalization process\n- `VNodeFlags.ClearInUseNormalized` - Opposite mask of InUse or Normalized\n\n**ChildFlags**\n\n- `ChildFlags.UnknownChildren` needs Normalization\n- `ChildFlags.HasInvalidChildren` is invalid (null, undefined, false, true)\n- `ChildFlags.HasVNodeChildren` (JSX **$HasVNodeChildren**) is single vNode (Element/Component)\n- `ChildFlags.HasNonKeyedChildren` (JSX **$HasNonKeyedChildren**) is Array of vNodes non keyed (no nesting, no holes)\n- `ChildFlags.HasKeyedChildren` (JSX **$HasKeyedChildren**) is Array of vNodes keyed (no nesting, no holes)\n- `ChildFlags.HasTextChildren` (JSX **$HasTextChildren**) vNode contains only text\n\n**ChildFlags Masks**\n\n- `ChildFlags.MultipleChildren` Is Array\n\nYou can easily combine multiple flags, by using bitwise operators. A common use case is an element that has keyed children:\n"
  },
  {
    "path": "packages/inferno-vnode-flags/index.cjs",
    "content": "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/index.min.cjs');\n} else {\n  module.exports = require('./dist/index.cjs');\n}\n"
  },
  {
    "path": "packages/inferno-vnode-flags/package.json",
    "content": "{\n  \"name\": \"inferno-vnode-flags\",\n  \"version\": \"9.0.11\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./index.cjs\",\n      \"types\": \"./dist/index.d.ts\"\n    },\n    \"./dist/index.dev.mjs\": \"./dist/index.dev.mjs\",\n    \"./dist/index.mjs\": \"./dist/index.mjs\"\n  },\n  \"description\": \"Provides an enum of all possible VNode Flags used when calling Inferno.createVNode\",\n  \"author\": {\n    \"name\": \"Dominic Gannaway\",\n    \"email\": \"dg@domgan.com\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/infernojs/inferno/issues\"\n  },\n  \"homepage\": \"https://github.com/infernojs/inferno#readme\",\n  \"keywords\": [\n    \"babel\",\n    \"react\",\n    \"inferno\",\n    \"framework\",\n    \"interfaces\",\n    \"user interfaces\",\n    \"html\",\n    \"renderToString\",\n    \"server\",\n    \"dom\",\n    \"browser\",\n    \"rollup\",\n    \"vnode\",\n    \"createVNode\",\n    \"flags\"\n  ],\n  \"rollup\": {\n    \"moduleName\": \"Inferno\"\n  },\n  \"files\": [\n    \"index.cjs\",\n    \"dist/\",\n    \"README.md\",\n    \"package.json\"\n  ],\n  \"module\": \"dist/index.mjs\",\n  \"dev:module\": \"dist/index.dev.mjs\",\n  \"typings\": \"dist/index.d.ts\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/infernojs/inferno.git\",\n    \"directory\": \"packages/inferno-vnode-flags\"\n  }\n}\n"
  },
  {
    "path": "packages/inferno-vnode-flags/src/index.ts",
    "content": "/* If editing these values check babel-plugin-also */\nexport const enum VNodeFlags {\n  /* First set of bits define shape of vNode */\n  Unknown = 0,\n  HtmlElement = 1,\n  ComponentUnknown = 1 << 1,\n  ComponentClass = 1 << 2,\n  ComponentFunction = 1 << 3,\n  Text = 1 << 4,\n\n  /* Special flags */\n  SvgElement = 1 << 5,\n  InputElement = 1 << 6,\n  TextareaElement = 1 << 7,\n  SelectElement = 1 << 8,\n  Portal = 1 << 10,\n  ReCreate = 1 << 11,\n  ContentEditable = 1 << 12,\n  Fragment = 1 << 13,\n  InUse = 1 << 14,\n  ForwardRef = 1 << 15,\n  Normalized = 1 << 16,\n\n  /* Masks */\n  ForwardRefComponent = ForwardRef | ComponentFunction,\n  FormElement = InputElement | TextareaElement | SelectElement,\n  Element = HtmlElement | SvgElement | FormElement,\n  Component = ComponentFunction | ComponentClass | ComponentUnknown,\n  DOMRef = Element | Text | Portal,\n  InUseOrNormalized = InUse | Normalized,\n  ClearInUse = ~InUse,\n  ComponentKnown = ComponentFunction | ComponentClass,\n}\n\n// Combinations are not possible, its bitwise only to reduce vNode size\nexport const enum ChildFlags {\n  UnknownChildren = 0, // When zero is passed children will be normalized\n  /* Second set of bits define shape of children */\n  HasInvalidChildren = 1,\n  HasVNodeChildren = 1 << 1,\n  HasNonKeyedChildren = 1 << 2,\n  HasKeyedChildren = 1 << 3,\n  HasTextChildren = 1 << 4,\n\n  MultipleChildren = HasNonKeyedChildren | HasKeyedChildren,\n}\n"
  },
  {
    "path": "scripts/bundle/bundle-size.js",
    "content": "import { readFileSync } from 'fs';\nimport { readFile, readdir } from 'fs/promises';\nimport Table from 'cli-table';\nimport { gzipSize } from 'gzip-size';\nimport { filesize } from 'filesize';\nimport { basename, dirname, join } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PACKAGES_DIR = join(__dirname, '../../packages/');\nconst INFERNO_VERSION = JSON.parse(readFileSync(join(__dirname, '../../package.json'))).version;\n\nasync function getFileSize(file) {\n  const data = await readFile(file, 'utf-8');\n  return {\n    fileSize: filesize(Buffer.byteLength(data)),\n    gzipSize: filesize(await gzipSize(data))\n  };\n}\n\nasync function printFileSizes() {\n  const files = await readdir(PACKAGES_DIR, { withFileTypes: true });\n  const dirs = files.filter((f) => f.isDirectory).map((dirent) => dirent.name);\n\n  // Exclude private packages\n  const packages = dirs.filter((d) => !JSON.parse(readFileSync(join(PACKAGES_DIR, d, 'package.json'))).private).map((file) => basename(file));\n\n  const table = new Table({\n    head: [\n      `INFERNO - ${INFERNO_VERSION}`,\n      'Browser' + ' (gzip)',\n      'Browser prod (min)' + ' (gzip)',\n      'mjs' + ' (gzip)',\n      'cjs' + ' (gzip)',\n      'cjs prod' + ' (gzip)'\n    ],\n    colWidth: [100, 200, 200, 200, 200]\n  });\n\n  for (const name of packages.sort()) {\n    const filesToStat = [name + '.js', name + '.min.js', 'index.mjs', 'index.cjs', 'index.min.cjs'];\n    const row = [name];\n\n    for (const file of filesToStat) {\n      const sizes = await getFileSize(`${PACKAGES_DIR}/${name}/dist/${file}`);\n\n      row.push(`${sizes.fileSize}/${sizes.gzipSize}`);\n    }\n    table.push(row);\n  }\n\n  console.log(table.toString());\n}\n\nprintFileSizes().catch((err) => {\n  console.error(err);\n});\n"
  },
  {
    "path": "scripts/bundle/move-compiled.js",
    "content": "import { readFileSync, cpSync } from 'fs';\nimport { join } from 'path';\n\nconst cwd = process.cwd();\nconst pkgJSONtext = readFileSync(join(cwd, 'package.json'));\nconst pkgJSON = JSON.parse(pkgJSONtext);\nif (!pkgJSON.private) {\n  cpSync(join(cwd, '../../build/packages/', pkgJSON.name, 'src'), join(cwd, 'tmpDist'), { recursive: true, force: true });\n}\n"
  },
  {
    "path": "scripts/bundle/move-typedefs.js",
    "content": "import { join } from 'path';\nimport { readFileSync, cpSync } from 'fs';\nimport { readFilesInDir } from './read-files-in-dir.js';\n\nconst cwd = process.cwd();\nconst pkgJSONtext = readFileSync(join(cwd, 'package.json'));\nconst pkgJSON = JSON.parse(pkgJSONtext);\n\nif (!pkgJSON.private) {\n  const allTsFiles = [];\n  const srcFolder = join(cwd, '../../build/packages/', pkgJSON.name, 'src');\n  const destFolder = join(cwd, 'dist');\n\n  readFilesInDir(srcFolder, (fileName) => {\n    if (fileName.endsWith('.ts')) {\n      allTsFiles.push({\n        absolutePath: fileName,\n        relativePath: fileName.substring(srcFolder.length)\n      });\n    }\n  });\n\n  for (const file of allTsFiles) {\n    cpSync(file.absolutePath, destFolder + file.relativePath, { recursive: true, force: true });\n  }\n}\n"
  },
  {
    "path": "scripts/bundle/read-files-in-dir.js",
    "content": "import { join } from 'path';\nimport { readdirSync, lstatSync, existsSync } from 'fs';\n\nexport function readFilesInDir(startPath, callback) {\n  if (!existsSync(startPath)) {\n    console.log('no dir ', startPath);\n    return;\n  }\n\n  const files = readdirSync(startPath);\n\n  for (let i = 0; i < files.length; i++) {\n    const filename = join(startPath, files[i]);\n    const stat = lstatSync(filename);\n    if (stat.isDirectory()) {\n      readFilesInDir(filename, callback); //recurse\n    } else {\n      callback(filename);\n    }\n  }\n}\n"
  },
  {
    "path": "scripts/fakedom/build.js",
    "content": "import {rollup} from \"rollup\";\nimport { existsSync, readdirSync, statSync } from \"fs\";\nimport commonjsPlugin from \"@rollup/plugin-commonjs\";\nimport nodeResolvePlugin from \"@rollup/plugin-node-resolve\";\nimport { dirname, join, resolve } from \"path\";\nimport replace from \"@rollup/plugin-replace\";\nimport terser from '@rollup/plugin-terser';\nimport alias from \"@rollup/plugin-alias\";\nimport { fileURLToPath } from \"url\";\nimport babel from \"@rollup/plugin-babel\";\nimport jsonPlugin from \"@rollup/plugin-json\"\n\nconst isProduction = process.env.NODE_ENV === 'production';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst benchmarks = readdirSync(__dirname).filter(file => statSync(join(__dirname, file)).isDirectory());\nconst resolvePkg = pkg => resolve(__dirname, '../../packages', pkg, 'dist', 'index.mjs');\n\n\nconsole.log(resolvePkg('inferno'));\n\n// see below for details on the options\nconst plugins = [\n  replace({\n    preventAssignment: true,\n    'process.env.NODE_ENV': '\"production\"',\n    sourcemap: false\n  }),\n  nodeResolvePlugin({\n    preferBuiltins: false\n  }),\n  babel({\n    exclude: 'node_modules/**',\n    sourceMaps: false,\n    babelrc: false,\n    plugins: [\n      ['babel-plugin-inferno', {imports: true, defineAllArguments: true}],\n    ]\n  }),\n  commonjsPlugin({\n    sourceMap: false\n  }),\n  jsonPlugin(),\n  alias({\n    resolve: ['.js'],\n    entries: [\n      {find: 'inferno', replacement: resolvePkg('inferno')},\n      {find: 'inferno-animation', replacement: resolvePkg('inferno-animation')},\n      {find: 'inferno-compat', replacement: resolvePkg('inferno-compat')},\n      {find: 'inferno-create-element', replacement: resolvePkg('inferno-create-element')},\n      {find: 'inferno-hydrate', replacement: resolvePkg('inferno-hydrate')},\n      {find: 'inferno-extras', replacement: resolvePkg('inferno-extras')},\n      {find: 'inferno-hyperscript', replacement: resolvePkg('inferno-hyperscript')},\n      {find: 'inferno-mobx', replacement: resolvePkg('inferno-mobx')},\n      {find: 'inferno-redux', replacement: resolvePkg('inferno-redux')},\n      {find: 'inferno-router', replacement: resolvePkg('inferno-router')},\n      {find: 'inferno-server', replacement: resolvePkg('inferno-server')},\n      {find: 'inferno-shared', replacement: resolvePkg('inferno-shared')},\n      {find: 'inferno-test-utils', replacement: resolvePkg('inferno-test-utils')},\n      {find: 'inferno-vnode-flags', replacement: resolvePkg('inferno-vnode-flags')},\n      {find: 'inferno-clone-vnode', replacement: resolvePkg('inferno-clone-vnode')},\n      {find: 'mobx', replacement: join(__dirname, '../../node_modules/mobx/dist/mobx.esm.js')}\n    ]\n  })\n];\n\nif (isProduction) {\n  plugins.push(\n    terser({\n      compress: {\n        ecma: 5,\n        inline: true,\n        if_return: false,\n        reduce_funcs: false,\n        passes: 5,\n        comparisons: false,\n      },\n      ie8: false,\n      mangle: {\n        toplevel: true\n      },\n      parse: {\n        html5_comments: false,\n        shebang: false\n      },\n      toplevel: false,\n      warnings: false\n    })\n  );\n}\n\nfor (const dir of benchmarks) {\n  const benchmarkPath = join(__dirname, dir);\n  const appJsPath = resolve(benchmarkPath, 'app.js')\n\n  // Don't build examples that don't have app.js\n  if (!existsSync(appJsPath)) continue;\n\n  const inputOptions = {\n    input: appJsPath,\n    external: ['os', 'fs', 'path', 'vm', 'url'],\n    plugins: plugins\n  };\n\n  const start = new Date();\n\n  console.log(`Build started -- ${start}`);\n\n  rollup(inputOptions).then(function (opts) {\n    return opts.write({\n      format: 'esm',\n      file: join(benchmarkPath, 'dist', 'bundle.js'),\n      sourcemap: false,\n      name: 'inferno'\n    });\n  });\n}\n"
  },
  {
    "path": "scripts/fakedom/libs/setup.js",
    "content": "import {JSDOM} from 'jsdom';\nconst dom = new JSDOM(`<!DOCTYPE html><html><body><div id=\"app\"></div></body></html>`);\n\nconst rafMock = Promise.resolve().then.bind(Promise.resolve());\n\nglobal.window = dom.window;\nglobal.document = dom.window.document;\nglobal.Node = dom.window.Node;\nglobal.window.requestAnimationFrame = rafMock\nglobal.requestAnimationFrame = rafMock;\n\nexport const container = dom.window.document.querySelector(\"#app\");\n"
  },
  {
    "path": "scripts/fakedom/libs/uibench.js",
    "content": "  var TableAlphabetLength = 10;\n  var TableAlphabets = [\n    \"0123456789\",\n    \"3057846291\",\n    \"8356294107\",\n    \"0861342795\",\n  ];\n  var HomeState = (function () {\n    function HomeState() {\n    }\n    HomeState.prototype.clone = function () {\n      return this;\n    };\n    return HomeState;\n  }());\n  var TableItemState = (function () {\n    function TableItemState(id, active, props) {\n      this.id = id;\n      this.active = active;\n      this.props = props;\n    }\n    TableItemState.prototype.clone = function () {\n      return new TableItemState(this.id, this.active, this.props.slice(0));\n    };\n    TableItemState.create = function (active, props) {\n      return new TableItemState(TableItemState._nextId++, active, props);\n    };\n    TableItemState._nextId = 0;\n    return TableItemState;\n  }());\n  var TableState = (function () {\n    function TableState(items) {\n      this.items = items;\n    }\n    TableState.prototype.clone = function () {\n      return new TableState(this.items.map(function (i) { return i.clone(); }));\n    };\n    TableState.create = function (rows, cols) {\n      var items = [];\n      for (var i = 0; i < rows; i++) {\n        var props = [];\n        for (var j = 0; j < cols; j++) {\n          var str = \"\";\n          var n = i;\n          var alphabet = TableAlphabets[j];\n          while (n >= TableAlphabetLength) {\n            str += alphabet[n % TableAlphabetLength];\n            n = n / TableAlphabetLength | 0;\n          }\n          str += alphabet[n % TableAlphabetLength];\n          props.push(str);\n        }\n        items.push(TableItemState.create(false, props));\n      }\n      return new TableState(items);\n    };\n    return TableState;\n  }());\n  var AnimBoxState = (function () {\n    function AnimBoxState(id, time) {\n      this.id = id;\n      this.time = time;\n    }\n    AnimBoxState.prototype.clone = function () {\n      return new AnimBoxState(this.id, this.time);\n    };\n    AnimBoxState.create = function (time) {\n      return new AnimBoxState(AnimBoxState._nextId++, time);\n    };\n    AnimBoxState._nextId = 0;\n    return AnimBoxState;\n  }());\n  var AnimState = (function () {\n    function AnimState(items) {\n      this.items = items;\n    }\n    AnimState.prototype.clone = function () {\n      return new AnimState(this.items.map(function (i) { return i.clone(); }));\n    };\n    AnimState.create = function (count) {\n      var items = [];\n      for (var i = 0; i < count; i++) {\n        items.push(AnimBoxState.create(0));\n      }\n      return new AnimState(items);\n    };\n    return AnimState;\n  }());\n  var TreeNodeState = (function () {\n    function TreeNodeState(id, container, children) {\n      this.id = id;\n      this.container = container;\n      this.children = children;\n    }\n    TreeNodeState.prototype.clone = function () {\n      return new TreeNodeState(this.id, this.container, this.children ? this.children.map(function (i) { return i.clone(); }) : this.children);\n    };\n    TreeNodeState.create = function (container, children) {\n      return new TreeNodeState(TreeNodeState._nextId++, container, children);\n    };\n    TreeNodeState._nextId = 0;\n    return TreeNodeState;\n  }());\n  var TreeState = (function () {\n    function TreeState(root) {\n      this.root = root;\n    }\n    TreeState.prototype.clone = function () {\n      return new TreeState(this.root.clone());\n    };\n    TreeState.create = function (hierarchy) {\n      function _create(depth) {\n        var count = hierarchy[depth];\n        var children = [];\n        var i;\n        if (depth === (hierarchy.length - 1)) {\n          for (i = 0; i < count; i++) {\n            children.push(TreeNodeState.create(false, null));\n          }\n        }\n        else {\n          for (i = 0; i < count; i++) {\n            children.push(TreeNodeState.create(true, _create(depth + 1)));\n          }\n        }\n        return children;\n      }\n      return new TreeState(TreeNodeState.create(true, _create(0)));\n    };\n    return TreeState;\n  }());\n  var AppState = (function () {\n    function AppState(location, home, table, anim, tree) {\n      this.location = location;\n      this.home = home;\n      this.table = table;\n      this.anim = anim;\n      this.tree = tree;\n    }\n    AppState.prototype.clone = function () {\n      return new AppState(this.location, this.home.clone(), this.table.clone(), this.anim.clone(), this.tree.clone());\n    };\n    return AppState;\n  }());\n\n  function switchTo(state, location) {\n    if (state.location === location) {\n      return state;\n    }\n    else {\n      return new AppState(location, state.home, state.table, state.anim, state.tree);\n    }\n  }\n  function tableCreate(state, rows, cols) {\n    return new AppState(state.location, state.home, TableState.create(rows, cols), state.anim, state.tree);\n  }\n  function tableFilterBy(state, nth) {\n    return new AppState(state.location, state.home, new TableState(state.table.items.filter(function (item, i) { return (i + 1) % nth; })), state.anim, state.tree);\n  }\n  function tableSortBy(state, i) {\n    var newItems = state.table.items.slice();\n    newItems.sort(function (a, b) { return a.props[i].localeCompare(b.props[i]); });\n    return new AppState(state.location, state.home, new TableState(newItems), state.anim, state.tree);\n  }\n  function tableActivateEach(state, nth) {\n    return new AppState(state.location, state.home, new TableState(state.table.items.map(function (item, i) { return (i + 1) % nth ?\n      item :\n      new TableItemState(item.id, true, item.props); })), state.anim, state.tree);\n  }\n  function animAdvanceEach(state, nth) {\n    return new AppState(state.location, state.home, state.table, new AnimState(state.anim.items.map(function (item, i) { return (i + 1) % nth ? item : new AnimBoxState(item.id, item.time + 1); })), state.tree);\n  }\n  function treeCreate(state, hierarchy) {\n    return new AppState(state.location, state.home, state.table, state.anim, TreeState.create(hierarchy));\n  }\n  function treeTransform(state, transformers) {\n    function transform(node, depth) {\n      var t = transformers[depth];\n      if (node.children !== null) {\n        var children = t(node.children);\n        if (depth < (transformers.length - 1)) {\n          children.map(function (item) { return transform(item, depth + 1); });\n        }\n        return new TreeNodeState(node.id, node.container, children);\n      }\n      return new TreeNodeState(node.id, node.container, null);\n    }\n    return new AppState(state.location, state.home, state.table, state.anim, new TreeState(transform(state.tree.root, 0)));\n  }\n\n  function reverse(children) {\n    var r = children.slice();\n    r.reverse();\n    return r;\n  }\n  function snabbdomWorstCase(children) {\n    var r = children.slice();\n    var a = r.shift();\n    var b = r.splice(r.length - 2, 1);\n    r.push(a, b[0]);\n    return r;\n  }\n  function insertFirst(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.unshift(TreeNodeState.create(false, null));\n      }\n      return children;\n    };\n  }\n  function insertLast(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.push(TreeNodeState.create(false, null));\n      }\n      return children;\n    };\n  }\n  function removeFirst(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.shift();\n      }\n      return children;\n    };\n  }\n  function removeLast(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.pop();\n      }\n      return children;\n    };\n  }\n  function moveFromEndToStart(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.unshift(children.pop());\n      }\n      return children;\n    };\n  }\n  function moveFromStartToEnd(n) {\n    return function (children) {\n      children = children.slice();\n      for (var i = 0; i < n; i++) {\n        children.push(children.shift());\n      }\n      return children;\n    };\n  }\n\n  function tableTests(onUpdate) {\n    var state = tableActivateEach(new AppState(\"table\", new HomeState(), TableState.create(2, 2), AnimState.create(0), TreeState.create([0])), 2);\n    state.table.items[0].id = 300;\n    state.table.items[1].id = 301;\n    onUpdate(state, \"update\");\n    var table = document.getElementsByClassName(\"Table\");\n    if (table.length !== 1) {\n      throw new Error(\"Spec test failed: table with Table className doesn't exists\");\n    }\n    var rows = document.getElementsByClassName(\"TableRow\");\n    if (rows.length !== 2) {\n      throw new Error(\"Spec test failed: invalid number of TableRows\");\n    }\n    if (rows[0].getAttribute(\"data-id\") !== \"300\") {\n      throw new Error(\"Spec test failed: invalid data-id attribute in the TableRow\");\n    }\n    if (rows[1].className.indexOf(\"active\") === -1) {\n      throw new Error(\"Spec test failed: TableRow should have active className when it is activated\");\n    }\n    var cells = document.getElementsByClassName(\"TableCell\");\n    if (cells.length !== 6) {\n      throw new Error(\"Spec test failed: invalid number of TableCells\");\n    }\n    if (cells[0].textContent !== \"#300\") {\n      throw new Error(\"Spec test failed: invalid textContent in the id TableCell\");\n    }\n    if (cells[1].textContent !== \"0\") {\n      throw new Error(\"Spec test failed: invalid textContent in the data TableCell\");\n    }\n    if (cells[2].textContent !== \"3\") {\n      throw new Error(\"Spec test failed: invalid textContent in the data TableCell\");\n    }\n    var logFn = console.log;\n    var clicked = false;\n    console.log = function () {\n      clicked = true;\n    };\n    cells[1].click();\n    console.log = logFn;\n    if (clicked === false) {\n      throw new Error(\"Spec test failed: TableCell doesn't have onClick event listener that prints to the console\");\n    }\n  }\n  function animTests(onUpdate) {\n    var state = new AppState(\"anim\", new HomeState(), TableState.create(0, 0), AnimState.create(2), TreeState.create([0]));\n    state.anim.items[0].id = 100;\n    state.anim.items[1].id = 101;\n    state = animAdvanceEach(state, 2);\n    onUpdate(state, \"update\");\n    var anim = document.getElementsByClassName(\"Anim\");\n    if (anim.length !== 1) {\n      throw new Error(\"Spec test failed: div with Anim className doesn't exists\");\n    }\n    var boxes = document.getElementsByClassName(\"AnimBox\");\n    if (boxes.length !== 2) {\n      throw new Error(\"Spec test failed: invalid number of AnimBoxes\");\n    }\n    if (boxes[0].getAttribute(\"data-id\") !== \"100\") {\n      throw new Error(\"Spec test failed: invalid data-id attribute in the AnimBox\");\n    }\n    if (boxes[0].style.borderRadius !== \"0px\") {\n      throw new Error(\"Spec test failed: invalid borderRadius style in the AnimBox\");\n    }\n    if (boxes[1].style.borderRadius !== \"1px\") {\n      throw new Error(\"Spec test failed: invalid borderRadius style in the AnimBox\");\n    }\n    if (!boxes[0].style.background) {\n      throw new Error(\"Spec test failed: invalid background style in the AnimBox\");\n    }\n  }\n  function treeTests(onUpdate) {\n    var state = new AppState(\"tree\", new HomeState(), TableState.create(0, 0), AnimState.create(0), TreeState.create([1, 2]));\n    state.tree.root.children[0].children[0].id = 2081;\n    state.tree.root.children[0].children[1].id = 2082;\n    onUpdate(state, \"update\");\n    var tree = document.getElementsByClassName(\"Tree\");\n    if (tree.length !== 1) {\n      throw new Error(\"Spec test failed: div with Tree className doesn't exists\");\n    }\n    var treeNodes = document.getElementsByClassName(\"TreeNode\");\n    if (treeNodes.length !== 2) {\n      throw new Error(\"Spec test failed: invalid number of TreeNodes\");\n    }\n    var treeLeafs = document.getElementsByClassName(\"TreeLeaf\");\n    if (treeLeafs.length !== 2) {\n      throw new Error(\"Spec test failed: invalid number of TreeLeafs\");\n    }\n    if (treeLeafs[0].textContent !== \"2081\") {\n      throw new Error(\"Spec test failed: invalid textContent in the TreeLeaf\");\n    }\n    if (treeLeafs[1].textContent !== \"2082\") {\n      throw new Error(\"Spec test failed: invalid textContent in the TreeLeaf\");\n    }\n  }\n  function specTest(onUpdate) {\n    var state = new AppState(\"table\", new HomeState(), TableState.create(0, 0), AnimState.create(0), TreeState.create([0]));\n    onUpdate(state, \"init\");\n    var mainTag = document.getElementsByClassName(\"Main\");\n    if (mainTag.length !== 1) {\n      throw new Error(\"Spec test failed: div tag with Main className doesn\\\"t exists\");\n    }\n    tableTests(onUpdate);\n    animTests(onUpdate);\n    treeTests(onUpdate);\n  }\n  function scuTest(onUpdate, onFinish) {\n    var state = new AppState(\"table\", new HomeState(), TableState.create(1, 1), AnimState.create(0), TreeState.create([0]));\n    state.table.items[0].props[0] = \"a\";\n    onUpdate(state, \"init\");\n    var node = document.getElementsByClassName(\"TableCell\")[1];\n    if (!node || node.textContent !== \"a\") {\n      throw new Error(\"SCU test failed\");\n    }\n    state.table.items[0].props[0] = \"b\";\n    onUpdate(state, \"update\");\n    node = document.getElementsByClassName(\"TableCell\")[1];\n    if (!node) {\n      throw new Error(\"SCU test failed\");\n    }\n    var result = true;\n    if (node.textContent !== \"a\") {\n      if (node.textContent === \"b\") {\n        result = false;\n      }\n      else {\n        throw new Error(\"SCU test failed\");\n      }\n    }\n    window.requestAnimationFrame(function () {\n      onFinish(result);\n    });\n  }\n  function recyclingTest(onUpdate, onFinish) {\n    var initialState = new AppState(\"tree\", new HomeState(), TableState.create(0, 0), AnimState.create(0), TreeState.create([0]));\n    var toState = treeCreate(initialState, [1]);\n    onUpdate(initialState, \"init\");\n    onUpdate(toState, \"update\");\n    var a = document.getElementsByClassName(\"TreeLeaf\")[0];\n    onUpdate(initialState, \"init\");\n    onUpdate(toState, \"update\");\n    var b = document.getElementsByClassName(\"TreeLeaf\")[0];\n    if (!a || !b) {\n      throw new Error(\"recycling test failed\");\n    }\n    var result = (a === b);\n    window.requestAnimationFrame(function () {\n      onFinish(result);\n    });\n  }\n  function preserveStateTest(onUpdate, onFinish) {\n    var state = \"uibench_\" + Math.random();\n    // Check tables\n    var tableInit = new AppState(\"table\", new HomeState(), TableState.create(3, 1), AnimState.create(0), TreeState.create([0]));\n    var tableUpdate = tableFilterBy(tableInit, 2);\n    onUpdate(tableInit, \"init\");\n    var tableRows = document.getElementsByClassName(\"TableRow\");\n    tableRows[2]._uibenchState = state;\n    onUpdate(tableUpdate, \"init\");\n    tableRows = document.getElementsByClassName(\"TableRow\");\n    var result = tableRows[1]._uibenchState === state;\n    // Check trees\n    var treeInit = new AppState(\"tree\", new HomeState(), TableState.create(0, 0), AnimState.create(0), TreeState.create([2]));\n    var treeUpdate = treeTransform(treeInit, [reverse]);\n    onUpdate(treeInit, \"init\");\n    var treeLeafs = document.getElementsByClassName(\"TreeLeaf\");\n    treeLeafs[0]._uibenchState = state;\n    onUpdate(treeUpdate, \"update\");\n    treeLeafs = document.getElementsByClassName(\"TreeLeaf\");\n    result = result && (treeLeafs[1]._uibenchState === state);\n    window.requestAnimationFrame(function () {\n      onFinish(result);\n    });\n  }\n\n  var TestCase = (function () {\n    function TestCase(name, from, to) {\n      this.name = name;\n      this.from = from;\n      this.to = to;\n    }\n    return TestCase;\n  }());\n  function testCase(name, from, to) {\n    return new TestCase(name, from, to);\n  }\n  var config = {\n    tests: null,\n    iterations: 5,\n    name: \"unnamed\",\n    version: \"0.0.0\",\n    mobile: false,\n    disableSCU: false,\n    enableDOMRecycling: false,\n    filter: null,\n    fullRenderTime: false,\n    timelineMarks: false,\n    disableChecks: false,\n  };\n  var timing = {\n    start: 0,\n    run: 0,\n    firstRender: 0,\n  };\n  function scuClone(state) {\n    if (config.disableSCU) {\n      state = state.clone();\n    }\n    return state;\n  }\n  function init(name, version, qs) {\n    config.name = name;\n    config.version = version;\n    if (qs[\"i\"] !== undefined) {\n      config.iterations = parseInt(qs[\"i\"], 10);\n    }\n    if (qs[\"name\"] !== undefined) {\n      config.name = qs[\"name\"];\n    }\n    if (qs[\"version\"] !== undefined) {\n      config.version = qs[\"version\"];\n    }\n    if (qs[\"mobile\"] !== undefined) {\n      config.mobile = true;\n    }\n    if (qs[\"disableSCU\"] !== undefined) {\n      config.disableSCU = true;\n    }\n    if (qs[\"enableDOMRecycling\"] !== undefined) {\n      config.enableDOMRecycling = true;\n    }\n    if (qs[\"filter\"] !== undefined) {\n      config.filter = qs[\"filter\"];\n    }\n    if (qs[\"fullRenderTime\"] !== undefined) {\n      config.fullRenderTime = true;\n    }\n    if (qs[\"timelineMarks\"] !== undefined) {\n      config.timelineMarks = true;\n    }\n    if (qs[\"disableChecks\"] !== undefined) {\n      config.disableChecks = true;\n    }\n    return config;\n  }\n  function initTests() {\n    var initial = new AppState(\"home\", new HomeState(), TableState.create(0, 0), AnimState.create(config.mobile ? 30 : 100), TreeState.create([0]));\n    var initialTable = switchTo(initial, \"table\");\n    var initialAnim = switchTo(initial, \"anim\");\n    var initialTree = switchTo(initial, \"tree\");\n    if (config.disableSCU) {\n      initialTable = initialTable.clone();\n      initialAnim = initialAnim.clone();\n      initialTree = initialTree.clone();\n    }\n    if (config.mobile) {\n      var table30_4 = tableCreate(initialTable, 30, 4);\n      var table15_4 = tableCreate(initialTable, 15, 4);\n      var table30_2 = tableCreate(initialTable, 30, 2);\n      var table15_2 = tableCreate(initialTable, 15, 2);\n      var tree50 = treeCreate(initialTree, [50]);\n      var tree5_10 = treeCreate(initialTree, [5, 10]);\n      var tree10_5 = treeCreate(initialTree, [10, 5]);\n      var tree10_10_10_2 = treeCreate(initialTree, [10, 10, 10, 2]);\n      var tree2__9 = treeCreate(initialTree, [2, 2, 2, 2, 2, 2, 2, 2, 2]);\n      if (config.disableSCU) {\n        table30_4 = table30_4.clone();\n        table15_4 = table15_4.clone();\n        table30_2 = table30_2.clone();\n        table15_2 = table15_2.clone();\n        tree50 = tree50.clone();\n        tree5_10 = tree5_10.clone();\n        tree10_5 = tree10_5.clone();\n      }\n      config.tests = [\n        testCase(\"table/[30,4]/render\", initialTable, scuClone(table30_4)),\n        testCase(\"table/[15,4]/render\", initialTable, scuClone(table15_4)),\n        testCase(\"table/[30,2]/render\", initialTable, scuClone(table30_2)),\n        testCase(\"table/[15,2]/render\", initialTable, scuClone(table15_2)),\n        testCase(\"table/[30,4]/removeAll\", table30_4, scuClone(initialTable)),\n        testCase(\"table/[15,4]/removeAll\", table15_4, scuClone(initialTable)),\n        testCase(\"table/[30,2]/removeAll\", table30_2, scuClone(initialTable)),\n        testCase(\"table/[15,2]/removeAll\", table15_2, scuClone(initialTable)),\n        testCase(\"table/[30,4]/sort/0\", table30_4, scuClone(tableSortBy(table30_4, 0))),\n        testCase(\"table/[15,4]/sort/0\", table15_4, scuClone(tableSortBy(table15_4, 0))),\n        testCase(\"table/[30,2]/sort/0\", table30_2, scuClone(tableSortBy(table30_2, 0))),\n        testCase(\"table/[15,2]/sort/0\", table15_2, scuClone(tableSortBy(table15_2, 0))),\n        testCase(\"table/[30,4]/sort/1\", table30_4, scuClone(tableSortBy(table30_4, 1))),\n        testCase(\"table/[15,4]/sort/1\", table15_4, scuClone(tableSortBy(table15_4, 1))),\n        testCase(\"table/[30,2]/sort/1\", table30_2, scuClone(tableSortBy(table30_2, 1))),\n        testCase(\"table/[15,2]/sort/1\", table15_2, scuClone(tableSortBy(table15_2, 1))),\n        testCase(\"table/[30,4]/filter/8\", table30_4, scuClone(tableFilterBy(table30_4, 8))),\n        testCase(\"table/[15,4]/filter/8\", table15_4, scuClone(tableFilterBy(table15_4, 8))),\n        testCase(\"table/[30,2]/filter/8\", table30_2, scuClone(tableFilterBy(table30_2, 8))),\n        testCase(\"table/[15,2]/filter/8\", table15_2, scuClone(tableFilterBy(table15_2, 8))),\n        testCase(\"table/[30,4]/filter/4\", table30_4, scuClone(tableFilterBy(table30_4, 4))),\n        testCase(\"table/[15,4]/filter/4\", table15_4, scuClone(tableFilterBy(table15_4, 4))),\n        testCase(\"table/[30,2]/filter/4\", table30_2, scuClone(tableFilterBy(table30_2, 4))),\n        testCase(\"table/[15,2]/filter/4\", table15_2, scuClone(tableFilterBy(table15_2, 4))),\n        testCase(\"table/[30,4]/filter/2\", table30_4, scuClone(tableFilterBy(table30_4, 2))),\n        testCase(\"table/[15,4]/filter/2\", table15_4, scuClone(tableFilterBy(table15_4, 2))),\n        testCase(\"table/[30,2]/filter/2\", table30_2, scuClone(tableFilterBy(table30_2, 2))),\n        testCase(\"table/[15,2]/filter/2\", table15_2, scuClone(tableFilterBy(table15_2, 2))),\n        testCase(\"table/[30,4]/activate/8\", table30_4, scuClone(tableActivateEach(table30_4, 8))),\n        testCase(\"table/[15,4]/activate/8\", table15_4, scuClone(tableActivateEach(table15_4, 8))),\n        testCase(\"table/[30,2]/activate/8\", table30_2, scuClone(tableActivateEach(table30_2, 8))),\n        testCase(\"table/[15,2]/activate/8\", table15_2, scuClone(tableActivateEach(table15_2, 8))),\n        testCase(\"table/[30,4]/activate/4\", table30_4, scuClone(tableActivateEach(table30_4, 4))),\n        testCase(\"table/[15,4]/activate/4\", table15_4, scuClone(tableActivateEach(table15_4, 4))),\n        testCase(\"table/[30,2]/activate/4\", table30_2, scuClone(tableActivateEach(table30_2, 4))),\n        testCase(\"table/[15,2]/activate/4\", table15_2, scuClone(tableActivateEach(table15_2, 4))),\n        testCase(\"table/[30,4]/activate/2\", table30_4, scuClone(tableActivateEach(table30_4, 2))),\n        testCase(\"table/[15,4]/activate/2\", table15_4, scuClone(tableActivateEach(table15_4, 2))),\n        testCase(\"table/[30,2]/activate/2\", table30_2, scuClone(tableActivateEach(table30_2, 2))),\n        testCase(\"table/[15,2]/activate/2\", table15_2, scuClone(tableActivateEach(table15_2, 2))),\n        testCase(\"anim/30/8\", initialAnim, scuClone(animAdvanceEach(initialAnim, 8))),\n        testCase(\"anim/30/4\", initialAnim, scuClone(animAdvanceEach(initialAnim, 4))),\n        testCase(\"anim/30/2\", initialAnim, scuClone(animAdvanceEach(initialAnim, 2))),\n        testCase(\"tree/[50]/render\", initialTree, scuClone(tree50)),\n        testCase(\"tree/[5,10]/render\", initialTree, scuClone(tree5_10)),\n        testCase(\"tree/[10,5]/render\", initialTree, scuClone(tree10_5)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2,2]/render\", initialTree, scuClone(tree2__9)),\n        testCase(\"tree/[50]/removeAll\", tree50, scuClone(initialTree)),\n        testCase(\"tree/[5,10]/removeAll\", tree5_10, scuClone(initialTree)),\n        testCase(\"tree/[10,5]/removeAll\", tree10_5, scuClone(initialTree)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2,2]/removeAll\", tree2__9, scuClone(initialTree)),\n        testCase(\"tree/[50]/[reverse]\", tree50, scuClone(treeTransform(tree50, [reverse]))),\n        testCase(\"tree/[5,10]/[reverse]\", tree5_10, scuClone(treeTransform(tree5_10, [reverse]))),\n        testCase(\"tree/[10,5]/[reverse]\", tree10_5, scuClone(treeTransform(tree10_5, [reverse]))),\n        testCase(\"tree/[50]/[insertFirst(1)]\", tree50, scuClone(treeTransform(tree50, [insertFirst(1)]))),\n        testCase(\"tree/[5,10]/[insertFirst(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [insertFirst(1)]))),\n        testCase(\"tree/[10,5]/[insertFirst(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [insertFirst(1)]))),\n        testCase(\"tree/[50]/[insertLast(1)]\", tree50, scuClone(treeTransform(tree50, [insertLast(1)]))),\n        testCase(\"tree/[5,10]/[insertLast(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [insertLast(1)]))),\n        testCase(\"tree/[10,5]/[insertLast(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [insertLast(1)]))),\n        testCase(\"tree/[50]/[removeFirst(1)]\", tree50, scuClone(treeTransform(tree50, [removeFirst(1)]))),\n        testCase(\"tree/[5,10]/[removeFirst(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [removeFirst(1)]))),\n        testCase(\"tree/[10,5]/[removeFirst(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [removeFirst(1)]))),\n        testCase(\"tree/[50]/[removeLast(1)]\", tree50, scuClone(treeTransform(tree50, [removeLast(1)]))),\n        testCase(\"tree/[5,10]/[removeLast(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [removeLast(1)]))),\n        testCase(\"tree/[10,5]/[removeLast(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [removeLast(1)]))),\n        testCase(\"tree/[50]/[moveFromEndToStart(1)]\", tree50, scuClone(treeTransform(tree50, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[5,10]/[moveFromEndToStart(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[10,5]/[moveFromEndToStart(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[50]/[moveFromStartToEnd(1)]\", tree50, scuClone(treeTransform(tree50, [moveFromStartToEnd(1)]))),\n        testCase(\"tree/[5,10]/[moveFromStartToEnd(1)]\", tree5_10, scuClone(treeTransform(tree5_10, [moveFromStartToEnd(1)]))),\n        testCase(\"tree/[10,5]/[moveFromStartToEnd(1)]\", tree10_5, scuClone(treeTransform(tree10_5, [moveFromStartToEnd(1)]))),\n        // special use case that should trigger worst case scenario for kivi library\n        testCase(\"tree/[50]/[kivi_worst_case]\", tree50, scuClone(treeTransform(treeTransform(treeTransform(tree50, [removeFirst(1)]), [removeLast(1)]), [reverse]))),\n        // special use case that should trigger worst case scenario for snabbdom library\n        testCase(\"tree/[50]/[snabbdom_worst_case]\", tree50, scuClone(treeTransform(tree50, [snabbdomWorstCase]))),\n        // special use case that should trigger worst case scenario for react library\n        testCase(\"tree/[50]/[react_worst_case]\", tree50, scuClone(treeTransform(treeTransform(treeTransform(tree50, [removeFirst(1)]), [removeLast(1)]), [moveFromEndToStart(1)]))),\n        // special use case that should trigger worst case scenario for virtual-dom library\n        testCase(\"tree/[50]/[virtual_dom_worst_case]\", tree50, scuClone(treeTransform(tree50, [moveFromStartToEnd(2)]))),\n        // test case with large amount of vnodes to test diff overhead\n        testCase(\"tree/[10,10,10,2]/no_change\", tree10_10_10_2, scuClone(tree10_10_10_2)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2]/no_change\", tree2__9, scuClone(tree2__9)),\n      ];\n    }\n    else {\n      var table100_4 = tableCreate(initialTable, 100, 4);\n      var table50_4 = tableCreate(initialTable, 50, 4);\n      var table100_2 = tableCreate(initialTable, 100, 2);\n      var table50_2 = tableCreate(initialTable, 50, 2);\n      var tree500 = treeCreate(initialTree, [500]);\n      var tree50_10 = treeCreate(initialTree, [50, 10]);\n      var tree10_50 = treeCreate(initialTree, [10, 50]);\n      var tree5_100 = treeCreate(initialTree, [5, 100]);\n      var tree10__4 = treeCreate(initialTree, [10, 10, 10, 10]);\n      var tree2__10 = treeCreate(initialTree, [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]);\n      if (config.disableSCU) {\n        table100_4 = table100_4.clone();\n        table50_4 = table50_4.clone();\n        table100_2 = table100_2.clone();\n        table50_2 = table50_2.clone();\n        tree500 = tree500.clone();\n        tree50_10 = tree50_10.clone();\n        tree10_50 = tree10_50.clone();\n        tree5_100 = tree5_100.clone();\n      }\n      config.tests = [\n        testCase(\"table/[100,4]/render\", initialTable, scuClone(table100_4)),\n        testCase(\"table/[50,4]/render\", initialTable, scuClone(table50_4)),\n        testCase(\"table/[100,2]/render\", initialTable, scuClone(table100_2)),\n        testCase(\"table/[50,2]/render\", initialTable, scuClone(table50_2)),\n        testCase(\"table/[100,4]/removeAll\", table100_4, scuClone(initialTable)),\n        testCase(\"table/[50,4]/removeAll\", table50_4, scuClone(initialTable)),\n        testCase(\"table/[100,2]/removeAll\", table100_2, scuClone(initialTable)),\n        testCase(\"table/[50,2]/removeAll\", table50_2, scuClone(initialTable)),\n        testCase(\"table/[100,4]/sort/0\", table100_4, scuClone(tableSortBy(table100_4, 0))),\n        testCase(\"table/[50,4]/sort/0\", table50_4, scuClone(tableSortBy(table50_4, 0))),\n        testCase(\"table/[100,2]/sort/0\", table100_2, scuClone(tableSortBy(table100_2, 0))),\n        testCase(\"table/[50,2]/sort/0\", table50_2, scuClone(tableSortBy(table50_2, 0))),\n        testCase(\"table/[100,4]/sort/1\", table100_4, scuClone(tableSortBy(table100_4, 1))),\n        testCase(\"table/[50,4]/sort/1\", table50_4, scuClone(tableSortBy(table50_4, 1))),\n        testCase(\"table/[100,2]/sort/1\", table100_2, scuClone(tableSortBy(table100_2, 1))),\n        testCase(\"table/[50,2]/sort/1\", table50_2, scuClone(tableSortBy(table50_2, 1))),\n        testCase(\"table/[100,4]/filter/32\", table100_4, scuClone(tableFilterBy(table100_4, 32))),\n        testCase(\"table/[50,4]/filter/32\", table50_4, scuClone(tableFilterBy(table50_4, 32))),\n        testCase(\"table/[100,2]/filter/32\", table100_2, scuClone(tableFilterBy(table100_2, 32))),\n        testCase(\"table/[50,2]/filter/32\", table50_2, scuClone(tableFilterBy(table50_2, 32))),\n        testCase(\"table/[100,4]/filter/16\", table100_4, scuClone(tableFilterBy(table100_4, 16))),\n        testCase(\"table/[50,4]/filter/16\", table50_4, scuClone(tableFilterBy(table50_4, 16))),\n        testCase(\"table/[100,2]/filter/16\", table100_2, scuClone(tableFilterBy(table100_2, 16))),\n        testCase(\"table/[50,2]/filter/16\", table50_2, scuClone(tableFilterBy(table50_2, 16))),\n        testCase(\"table/[100,4]/filter/8\", table100_4, scuClone(tableFilterBy(table100_4, 8))),\n        testCase(\"table/[50,4]/filter/8\", table50_4, scuClone(tableFilterBy(table50_4, 8))),\n        testCase(\"table/[100,2]/filter/8\", table100_2, scuClone(tableFilterBy(table100_2, 8))),\n        testCase(\"table/[50,2]/filter/8\", table50_2, scuClone(tableFilterBy(table50_2, 8))),\n        testCase(\"table/[100,4]/filter/4\", table100_4, scuClone(tableFilterBy(table100_4, 4))),\n        testCase(\"table/[50,4]/filter/4\", table50_4, scuClone(tableFilterBy(table50_4, 4))),\n        testCase(\"table/[100,2]/filter/4\", table100_2, scuClone(tableFilterBy(table100_2, 4))),\n        testCase(\"table/[50,2]/filter/4\", table50_2, scuClone(tableFilterBy(table50_2, 4))),\n        testCase(\"table/[100,4]/activate/32\", table100_4, scuClone(tableActivateEach(table100_4, 32))),\n        testCase(\"table/[50,4]/activate/32\", table50_4, scuClone(tableActivateEach(table50_4, 32))),\n        testCase(\"table/[100,2]/activate/32\", table100_2, scuClone(tableActivateEach(table100_2, 32))),\n        testCase(\"table/[50,2]/activate/32\", table50_2, scuClone(tableActivateEach(table50_2, 32))),\n        testCase(\"table/[100,4]/activate/16\", table100_4, scuClone(tableActivateEach(table100_4, 16))),\n        testCase(\"table/[50,4]/activate/16\", table50_4, scuClone(tableActivateEach(table50_4, 16))),\n        testCase(\"table/[100,2]/activate/16\", table100_2, scuClone(tableActivateEach(table100_2, 16))),\n        testCase(\"table/[50,2]/activate/16\", table50_2, scuClone(tableActivateEach(table50_2, 16))),\n        testCase(\"table/[100,4]/activate/8\", table100_4, scuClone(tableActivateEach(table100_4, 8))),\n        testCase(\"table/[50,4]/activate/8\", table50_4, scuClone(tableActivateEach(table50_4, 8))),\n        testCase(\"table/[100,2]/activate/8\", table100_2, scuClone(tableActivateEach(table100_2, 8))),\n        testCase(\"table/[50,2]/activate/8\", table50_2, scuClone(tableActivateEach(table50_2, 8))),\n        testCase(\"table/[100,4]/activate/4\", table100_4, scuClone(tableActivateEach(table100_4, 4))),\n        testCase(\"table/[50,4]/activate/4\", table50_4, scuClone(tableActivateEach(table50_4, 4))),\n        testCase(\"table/[100,2]/activate/4\", table100_2, scuClone(tableActivateEach(table100_2, 4))),\n        testCase(\"table/[50,2]/activate/4\", table50_2, scuClone(tableActivateEach(table50_2, 4))),\n        testCase(\"anim/100/32\", initialAnim, scuClone(animAdvanceEach(initialAnim, 32))),\n        testCase(\"anim/100/16\", initialAnim, scuClone(animAdvanceEach(initialAnim, 16))),\n        testCase(\"anim/100/8\", initialAnim, scuClone(animAdvanceEach(initialAnim, 8))),\n        testCase(\"anim/100/4\", initialAnim, scuClone(animAdvanceEach(initialAnim, 4))),\n        testCase(\"tree/[500]/render\", initialTree, scuClone(tree500)),\n        testCase(\"tree/[50,10]/render\", initialTree, scuClone(tree50_10)),\n        testCase(\"tree/[10,50]/render\", initialTree, scuClone(tree10_50)),\n        testCase(\"tree/[5,100]/render\", initialTree, scuClone(tree5_100)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2,2,2]/render\", initialTree, scuClone(tree2__10)),\n        testCase(\"tree/[500]/removeAll\", tree500, scuClone(initialTree)),\n        testCase(\"tree/[50,10]/removeAll\", tree50_10, scuClone(initialTree)),\n        testCase(\"tree/[10,50]/removeAll\", tree10_50, scuClone(initialTree)),\n        testCase(\"tree/[5,100]/removeAll\", tree5_100, scuClone(initialTree)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2,2,2]/removeAll\", tree2__10, scuClone(initialTree)),\n        testCase(\"tree/[500]/[reverse]\", tree500, scuClone(treeTransform(tree500, [reverse]))),\n        testCase(\"tree/[50,10]/[reverse]\", tree50_10, scuClone(treeTransform(tree50_10, [reverse]))),\n        testCase(\"tree/[10,50]/[reverse]\", tree10_50, scuClone(treeTransform(tree10_50, [reverse]))),\n        testCase(\"tree/[5,100]/[reverse]\", tree5_100, scuClone(treeTransform(tree5_100, [reverse]))),\n        testCase(\"tree/[500]/[insertFirst(1)]\", tree500, scuClone(treeTransform(tree500, [insertFirst(1)]))),\n        testCase(\"tree/[50,10]/[insertFirst(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [insertFirst(1)]))),\n        testCase(\"tree/[10,50]/[insertFirst(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [insertFirst(1)]))),\n        testCase(\"tree/[5,100]/[insertFirst(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [insertFirst(1)]))),\n        testCase(\"tree/[500]/[insertLast(1)]\", tree500, scuClone(treeTransform(tree500, [insertLast(1)]))),\n        testCase(\"tree/[50,10]/[insertLast(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [insertLast(1)]))),\n        testCase(\"tree/[10,50]/[insertLast(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [insertLast(1)]))),\n        testCase(\"tree/[5,100]/[insertLast(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [insertLast(1)]))),\n        testCase(\"tree/[500]/[removeFirst(1)]\", tree500, scuClone(treeTransform(tree500, [removeFirst(1)]))),\n        testCase(\"tree/[50,10]/[removeFirst(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [removeFirst(1)]))),\n        testCase(\"tree/[10,50]/[removeFirst(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [removeFirst(1)]))),\n        testCase(\"tree/[5,100]/[removeFirst(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [removeFirst(1)]))),\n        testCase(\"tree/[500]/[removeLast(1)]\", tree500, scuClone(treeTransform(tree500, [removeLast(1)]))),\n        testCase(\"tree/[50,10]/[removeLast(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [removeLast(1)]))),\n        testCase(\"tree/[10,50]/[removeLast(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [removeLast(1)]))),\n        testCase(\"tree/[5,100]/[removeLast(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [removeLast(1)]))),\n        testCase(\"tree/[500]/[moveFromEndToStart(1)]\", tree500, scuClone(treeTransform(tree500, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[50,10]/[moveFromEndToStart(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[10,50]/[moveFromEndToStart(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[5,100]/[moveFromEndToStart(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [moveFromEndToStart(1)]))),\n        testCase(\"tree/[500]/[moveFromStartToEnd(1)]\", tree500, scuClone(treeTransform(tree500, [moveFromStartToEnd(1)]))),\n        testCase(\"tree/[50,10]/[moveFromStartToEnd(1)]\", tree50_10, scuClone(treeTransform(tree50_10, [moveFromStartToEnd(1)]))),\n        testCase(\"tree/[10,50]/[moveFromStartToEnd(1)]\", tree10_50, scuClone(treeTransform(tree10_50, [moveFromStartToEnd(1)]))),\n        testCase(\"tree/[5,100]/[moveFromStartToEnd(1)]\", tree5_100, scuClone(treeTransform(tree5_100, [moveFromStartToEnd(1)]))),\n        // special use case that should trigger worst case scenario for kivi library\n        testCase(\"tree/[500]/[kivi_worst_case]\", tree500, scuClone(treeTransform(treeTransform(treeTransform(tree500, [removeFirst(1)]), [removeLast(1)]), [reverse]))),\n        // special use case that should trigger worst case scenario for snabbdom library\n        testCase(\"tree/[500]/[snabbdom_worst_case]\", tree500, scuClone(treeTransform(tree500, [snabbdomWorstCase]))),\n        // special use case that should trigger worst case scenario for react library\n        testCase(\"tree/[500]/[react_worst_case]\", tree500, scuClone(treeTransform(treeTransform(treeTransform(tree500, [removeFirst(1)]), [removeLast(1)]), [moveFromEndToStart(1)]))),\n        // special use case that should trigger worst case scenario for virtual-dom library\n        testCase(\"tree/[500]/[virtual_dom_worst_case]\", tree500, scuClone(treeTransform(tree500, [moveFromStartToEnd(2)]))),\n        // test case with large amount of vnodes to test diff overhead\n        testCase(\"tree/[10,10,10,10]/no_change\", tree10__4, scuClone(tree10__4)),\n        testCase(\"tree/[2,2,2,2,2,2,2,2,2,2]/no_change\", tree2__10, scuClone(tree2__10)),\n      ];\n    }\n  }\n  var macrotasks = [];\n\n  var Executor = (function () {\n    function Executor(iterations, groups, onUpdate, onFinish, onProgress) {\n      var _this = this;\n      this._next = function () {\n        var group = _this.groups[_this._currentGroup];\n        if (_this._state === \"init\") {\n          if (config.timelineMarks) {\n            console.timeStamp(\"init \" + group.name);\n          }\n          _this.onUpdate(group.from, \"init\");\n          _this._state = \"update\";\n          requestAnimationFrame(_this._next);\n        }\n        else if (_this._state === \"update\") {\n          if (config.timelineMarks) {\n            console.timeStamp(\"update \" + group.name);\n          }\n          _this._startTime = window.performance.now();\n          _this.onUpdate(group.to, \"update\");\n          _this._state = \"measure_time\";\n          _this._next();\n        }\n        else {\n          var t = window.performance.now() - _this._startTime;\n          if (config.timelineMarks) {\n            console.timeStamp(\"measure_time \" + group.name);\n          }\n          // _this.onProgress((_this._currentIteration * _this.groups.length + _this._currentGroup) / (_this.groups.length * _this.iterations));\n          var samples = _this._samples[group.name];\n          if (samples === undefined) {\n            samples = _this._samples[group.name] = [];\n          }\n          samples.push(t);\n          _this._state = \"init\";\n          _this._currentGroup++;\n          if (_this._currentGroup < _this.groups.length) {\n            requestAnimationFrame(_this._next);\n          }\n          else {\n            _this._currentIteration++;\n            if (_this._currentIteration < _this.iterations) {\n              _this._currentGroup = 0;\n              requestAnimationFrame(_this._next);\n            }\n            else {\n              _this.onFinish(_this._samples);\n              // _this.onProgress(1);\n            }\n          }\n        }\n      };\n      this.iterations = iterations;\n      this.groups = groups;\n      this.onUpdate = onUpdate;\n      this.onFinish = onFinish;\n      // this.onProgress = onProgress;\n      this._samples = {};\n      this._state = \"init\";\n      this._currentGroup = 0;\n      this._currentIteration = 0;\n      this._startTime = 0;\n    }\n    Executor.prototype.run = function () {\n      this._next();\n    };\n    return Executor;\n  }());\n  function firstRenderTime(onUpdate, done) {\n    var state = new AppState(\"table\", new HomeState(), config.mobile ? TableState.create(30, 4) : TableState.create(100, 4), AnimState.create(0), TreeState.create([0]));\n    var t = performance.now();\n    onUpdate(state, \"init\");\n    function finish() {\n      timing.firstRender = performance.now() - t;\n      done();\n    }\n\n    finish();\n  }\n  function run(onUpdate, onFinish, filter, testCb) {\n    timing.run = performance.now();\n    firstRenderTime(onUpdate, function () {\n      if (!config.disableChecks) {\n        specTest(onUpdate);\n      }\n      scuTest(onUpdate, function (scuSupported) {\n        recyclingTest(onUpdate, function (recyclingEnabled) {\n          preserveStateTest(onUpdate, function (preserveState) {\n            initTests();\n            var tests = config.tests;\n            var name = config.name;\n            filter = filter || config.filter;\n            if (tests && filter) {\n              tests = tests.filter(function (t) { return t.name.indexOf(filter) !== -1; });\n            }\n\n            function run() {\n              var e = new Executor(config.iterations, tests, onUpdate, function (samples) {\n                onFinish(samples);\n              }, testCb);\n              e.run();\n            }\n            if (tests) {\n              run();\n            }\n            else {\n              onFinish({});\n            }\n          });\n        });\n      });\n    });\n  }\n  timing.start = performance.now();\n\n  export { config, init, run, TestCase }\n"
  },
  {
    "path": "scripts/fakedom/results/inferno_base_line.json",
    "content": "[[{\"round\":0,\"log\":0,\"cpu\":25.901195000857115,\"memory\":8.47},{\"round\":0,\"log\":1,\"cpu\":5.526951000094414,\"memory\":10.03},{\"round\":0,\"log\":2,\"cpu\":1.1100139990448952,\"memory\":10.12},{\"round\":0,\"log\":3,\"cpu\":1.7492510005831718,\"memory\":10.2},{\"round\":0,\"log\":4,\"cpu\":0.39515800029039383,\"memory\":10.23},{\"round\":0,\"log\":5,\"cpu\":0.19655799865722656,\"memory\":10.25},{\"round\":0,\"log\":6,\"cpu\":0.19476900063455105,\"memory\":10.27},{\"round\":0,\"log\":7,\"cpu\":1.1009550001472235,\"memory\":10.7},{\"round\":0,\"log\":8,\"cpu\":0.2934680003672838,\"memory\":10.73},{\"round\":0,\"log\":9,\"cpu\":0.486158000305295,\"memory\":10.8},{\"round\":0,\"log\":10,\"cpu\":0.3843479994684458,\"memory\":10.82},{\"round\":0,\"log\":11,\"cpu\":7.4883110001683235,\"memory\":12.55},{\"round\":0,\"log\":12,\"cpu\":21.750975999981165,\"memory\":7.7},{\"round\":0,\"log\":13,\"cpu\":2.7707160003483295,\"memory\":8.95},{\"round\":0,\"log\":14,\"cpu\":9.686959998682141,\"memory\":12.59},{\"round\":0,\"log\":15,\"cpu\":1.2241230010986328,\"memory\":13.22},{\"round\":0,\"log\":16,\"cpu\":13.494200000539422,\"memory\":5.07},{\"round\":0,\"log\":17,\"cpu\":1.5290309991687536,\"memory\":5.93},{\"round\":0,\"log\":18,\"cpu\":4.698316000401974,\"memory\":8.22},{\"round\":0,\"log\":19,\"cpu\":12.800002999603748,\"memory\":15.38},{\"round\":0,\"log\":20,\"cpu\":1.9671000000089407,\"memory\":16.54},{\"round\":0,\"log\":21,\"cpu\":5.434461999684572,\"memory\":5.07},{\"round\":0,\"log\":22,\"cpu\":0.8795650005340576,\"memory\":5.65},{\"round\":0,\"log\":23,\"cpu\":5.746249999850988,\"memory\":9.88},{\"round\":0,\"log\":24,\"cpu\":0.9790850002318621,\"memory\":10.68},{\"round\":0,\"log\":25,\"cpu\":2.731936000287533,\"memory\":12.79},{\"round\":0,\"log\":26,\"cpu\":0.5543269999325275,\"memory\":13.2},{\"round\":0,\"log\":27,\"cpu\":9.217712000012398,\"memory\":6.26},{\"round\":0,\"log\":28,\"cpu\":2.8239350002259016,\"memory\":8.13},{\"round\":0,\"log\":29,\"cpu\":4.976443998515606,\"memory\":12.7},{\"round\":0,\"log\":30,\"cpu\":0.8619160000234842,\"memory\":13.47},{\"round\":0,\"log\":31,\"cpu\":5.597030000761151,\"memory\":18.33},{\"round\":0,\"log\":32,\"cpu\":2.362337999045849,\"memory\":5.85},{\"round\":0,\"log\":33,\"cpu\":3.486142000183463,\"memory\":8.8},{\"round\":0,\"log\":34,\"cpu\":0.691686000674963,\"memory\":9.35},{\"round\":0,\"log\":35,\"cpu\":7.122742999345064,\"memory\":15.97},{\"round\":0,\"log\":36,\"cpu\":2.0268890000879765,\"memory\":17.76},{\"round\":0,\"log\":37,\"cpu\":5.322773000225425,\"memory\":9.28},{\"round\":0,\"log\":38,\"cpu\":0.9667950011789799,\"memory\":10.12},{\"round\":0,\"log\":39,\"cpu\":4.776854999363422,\"memory\":14.87},{\"round\":0,\"log\":40,\"cpu\":1.6306010000407696,\"memory\":16.15},{\"round\":0,\"log\":41,\"cpu\":3.9058400001376867,\"memory\":6.28},{\"round\":0,\"log\":42,\"cpu\":0.7503859996795654,\"memory\":6.88},{\"round\":0,\"log\":43,\"cpu\":6.585826000198722,\"memory\":13.41},{\"round\":0,\"log\":44,\"cpu\":0.22388899885118008,\"memory\":13.46},{\"round\":0,\"log\":45,\"cpu\":4.414016000926495,\"memory\":17.64},{\"round\":0,\"log\":46,\"cpu\":0.08246999979019165,\"memory\":17.67},{\"round\":0,\"log\":47,\"cpu\":5.279013000428677,\"memory\":8.5},{\"round\":0,\"log\":48,\"cpu\":0.27172799967229366,\"memory\":8.55},{\"round\":0,\"log\":49,\"cpu\":3.0060239993035793,\"memory\":11.4},{\"round\":0,\"log\":50,\"cpu\":0.08064000122249126,\"memory\":11.42},{\"round\":0,\"log\":51,\"cpu\":6.525125999003649,\"memory\":17.93},{\"round\":0,\"log\":52,\"cpu\":0.26098900102078915,\"memory\":18.02},{\"round\":0,\"log\":53,\"cpu\":5.013303998857737,\"memory\":9.27},{\"round\":0,\"log\":54,\"cpu\":0.1049790009856224,\"memory\":9.32},{\"round\":0,\"log\":55,\"cpu\":4.393826998770237,\"memory\":14.02},{\"round\":0,\"log\":56,\"cpu\":0.1522390004247427,\"memory\":14.09},{\"round\":0,\"log\":57,\"cpu\":3.0740040000528097,\"memory\":16.92},{\"round\":0,\"log\":58,\"cpu\":0.10308900102972984,\"memory\":16.96},{\"round\":0,\"log\":59,\"cpu\":6.752735998481512,\"memory\":9.65},{\"round\":0,\"log\":60,\"cpu\":0.28077800013124943,\"memory\":9.82},{\"round\":0,\"log\":61,\"cpu\":4.034459000453353,\"memory\":13.9},{\"round\":0,\"log\":62,\"cpu\":0.15577900037169456,\"memory\":13.98},{\"round\":0,\"log\":63,\"cpu\":4.821234999224544,\"memory\":18.64},{\"round\":0,\"log\":64,\"cpu\":0.22044900059700012,\"memory\":18.77},{\"round\":0,\"log\":65,\"cpu\":3.3495720010250807,\"memory\":7.61},{\"round\":0,\"log\":66,\"cpu\":0.1622599996626377,\"memory\":7.67},{\"round\":0,\"log\":67,\"cpu\":5.779748998582363,\"memory\":14.14},{\"round\":0,\"log\":68,\"cpu\":0.4255079999566078,\"memory\":14.46},{\"round\":0,\"log\":69,\"cpu\":3.8384400010108948,\"memory\":18.39},{\"round\":0,\"log\":70,\"cpu\":0.24157899990677834,\"memory\":18.55},{\"round\":0,\"log\":71,\"cpu\":4.995293999090791,\"memory\":8.64},{\"round\":0,\"log\":72,\"cpu\":0.3662180006504059,\"memory\":8.87},{\"round\":0,\"log\":73,\"cpu\":2.5429570004343987,\"memory\":11.55},{\"round\":0,\"log\":74,\"cpu\":0.18011900037527084,\"memory\":11.66},{\"round\":0,\"log\":75,\"cpu\":5.856968998908997,\"memory\":18.08},{\"round\":0,\"log\":76,\"cpu\":0.2812790013849735,\"memory\":18.11},{\"round\":0,\"log\":77,\"cpu\":5.734519999474287,\"memory\":9.64},{\"round\":0,\"log\":78,\"cpu\":0.05900999903678894,\"memory\":9.66},{\"round\":0,\"log\":79,\"cpu\":5.103903001174331,\"memory\":14.47},{\"round\":0,\"log\":80,\"cpu\":0.09697899967432022,\"memory\":14.49},{\"round\":0,\"log\":81,\"cpu\":3.534401999786496,\"memory\":17.37},{\"round\":0,\"log\":82,\"cpu\":0.0603800006210804,\"memory\":17.38},{\"round\":0,\"log\":83,\"cpu\":7.208931999281049,\"memory\":9.84},{\"round\":0,\"log\":84,\"cpu\":0.1088590007275343,\"memory\":9.87},{\"round\":0,\"log\":85,\"cpu\":4.595185998827219,\"memory\":14.08},{\"round\":0,\"log\":86,\"cpu\":0.08263999968767166,\"memory\":14.1},{\"round\":0,\"log\":87,\"cpu\":5.1823230013251305,\"memory\":18.8},{\"round\":0,\"log\":88,\"cpu\":0.09670899994671345,\"memory\":18.83},{\"round\":0,\"log\":89,\"cpu\":4.176958998665214,\"memory\":7.97},{\"round\":0,\"log\":90,\"cpu\":0.06599900126457214,\"memory\":7.98},{\"round\":0,\"log\":91,\"cpu\":5.744319999590516,\"memory\":14.43},{\"round\":0,\"log\":92,\"cpu\":0.12401000037789345,\"memory\":14.48},{\"round\":0,\"log\":93,\"cpu\":4.0578680001199245,\"memory\":18.65},{\"round\":0,\"log\":94,\"cpu\":0.077029999345541,\"memory\":18.68},{\"round\":0,\"log\":95,\"cpu\":4.956204000860453,\"memory\":9.19},{\"round\":0,\"log\":96,\"cpu\":0.1191600002348423,\"memory\":9.23},{\"round\":0,\"log\":97,\"cpu\":2.63871599920094,\"memory\":12.08},{\"round\":0,\"log\":98,\"cpu\":0.07102899998426437,\"memory\":12.1},{\"round\":0,\"log\":99,\"cpu\":6.255057999864221,\"memory\":18.54},{\"round\":0,\"log\":100,\"cpu\":0.22339900024235249,\"memory\":18.62},{\"round\":0,\"log\":101,\"cpu\":5.4583010002970695,\"memory\":10.06},{\"round\":0,\"log\":102,\"cpu\":0.08681999891996384,\"memory\":10.09},{\"round\":0,\"log\":103,\"cpu\":4.1045380011200905,\"memory\":14.76},{\"round\":0,\"log\":104,\"cpu\":0.13263999857008457,\"memory\":14.83},{\"round\":0,\"log\":105,\"cpu\":2.8429550006985664,\"memory\":17.68},{\"round\":0,\"log\":106,\"cpu\":0.0820700004696846,\"memory\":17.71},{\"round\":0,\"log\":107,\"cpu\":9.694358998909593,\"memory\":6.49},{\"round\":0,\"log\":108,\"cpu\":0.31779800169169903,\"memory\":6.58},{\"round\":0,\"log\":109,\"cpu\":0.19970900006592274,\"memory\":6.66},{\"round\":0,\"log\":110,\"cpu\":0.34777799993753433,\"memory\":6.8},{\"round\":0,\"log\":111,\"cpu\":0.31990799866616726,\"memory\":6.95},{\"round\":0,\"log\":112,\"cpu\":0.587907001376152,\"memory\":7.22},{\"round\":0,\"log\":113,\"cpu\":0.5701369997113943,\"memory\":7.49},{\"round\":0,\"log\":114,\"cpu\":1.223794000223279,\"memory\":8.04},{\"round\":0,\"log\":115,\"cpu\":0.21670899912714958,\"memory\":8.17},{\"round\":0,\"log\":116,\"cpu\":5.844380000606179,\"memory\":13.37},{\"round\":0,\"log\":117,\"cpu\":2.5568760000169277,\"memory\":15.23},{\"round\":0,\"log\":118,\"cpu\":6.967573998495936,\"memory\":7.57},{\"round\":0,\"log\":119,\"cpu\":1.270473001524806,\"memory\":8.67},{\"round\":0,\"log\":120,\"cpu\":5.017113998532295,\"memory\":13.9},{\"round\":0,\"log\":121,\"cpu\":0.7433560006320477,\"memory\":14.8},{\"round\":0,\"log\":122,\"cpu\":4.968094000592828,\"memory\":19.73},{\"round\":0,\"log\":123,\"cpu\":1.7916209995746613,\"memory\":7.29},{\"round\":0,\"log\":124,\"cpu\":20.447053000330925,\"memory\":16.02},{\"round\":0,\"log\":125,\"cpu\":12.615784998983145,\"memory\":17.31},{\"round\":0,\"log\":126,\"cpu\":2.1791380010545254,\"memory\":19.06},{\"round\":0,\"log\":127,\"cpu\":4.924635000526905,\"memory\":24.23},{\"round\":0,\"log\":128,\"cpu\":1.0100339986383915,\"memory\":25.25},{\"round\":0,\"log\":129,\"cpu\":6.0433290004730225,\"memory\":19.4},{\"round\":0,\"log\":130,\"cpu\":0.9067950006574392,\"memory\":20.3},{\"round\":0,\"log\":131,\"cpu\":4.107818000018597,\"memory\":25.12},{\"round\":0,\"log\":132,\"cpu\":0.7321069985628128,\"memory\":26.01},{\"round\":0,\"log\":133,\"cpu\":20.993970001116395,\"memory\":30.09},{\"round\":0,\"log\":134,\"cpu\":3.7613510005176067,\"memory\":32.95},{\"round\":0,\"log\":135,\"cpu\":7.468680998310447,\"memory\":30.42},{\"round\":0,\"log\":136,\"cpu\":8.276897000148892,\"memory\":34.16},{\"round\":0,\"log\":137,\"cpu\":10.772193001583219,\"memory\":31.75},{\"round\":0,\"log\":138,\"cpu\":1.9010099992156029,\"memory\":33.57},{\"round\":0,\"log\":139,\"cpu\":6.033769000321627,\"memory\":39.56},{\"round\":0,\"log\":140,\"cpu\":1.1184940002858639,\"memory\":41.01},{\"round\":0,\"log\":141,\"cpu\":7.824988998472691,\"memory\":37.41},{\"round\":0,\"log\":142,\"cpu\":0.872486000880599,\"memory\":38.67},{\"round\":0,\"log\":143,\"cpu\":5.7670900002121925,\"memory\":44.67},{\"round\":0,\"log\":144,\"cpu\":0.13873899914324284,\"memory\":44.76},{\"round\":0,\"log\":145,\"cpu\":9.060403000563383,\"memory\":42.89},{\"round\":0,\"log\":146,\"cpu\":0.06859900057315826,\"memory\":42.91},{\"round\":0,\"log\":147,\"cpu\":5.147323999553919,\"memory\":48.75},{\"round\":0,\"log\":148,\"cpu\":0.05102900043129921,\"memory\":48.77},{\"round\":0,\"log\":149,\"cpu\":7.086092999204993,\"memory\":46.94},{\"round\":0,\"log\":150,\"cpu\":0.05582999996840954,\"memory\":46.95},{\"round\":0,\"log\":151,\"cpu\":8.102228000760078,\"memory\":46.18},{\"round\":0,\"log\":152,\"cpu\":0.1444690003991127,\"memory\":46.26},{\"round\":0,\"log\":153,\"cpu\":6.633855998516083,\"memory\":53.17},{\"round\":0,\"log\":154,\"cpu\":0.061778999865055084,\"memory\":53.19},{\"round\":0,\"log\":155,\"cpu\":7.249273000285029,\"memory\":51.36},{\"round\":0,\"log\":156,\"cpu\":0.05332900024950504,\"memory\":51.38},{\"round\":0,\"log\":157,\"cpu\":4.952293999493122,\"memory\":57.07},{\"round\":0,\"log\":158,\"cpu\":0.05263000167906284,\"memory\":57.08},{\"round\":0,\"log\":159,\"cpu\":7.683269999921322,\"memory\":55.68},{\"round\":0,\"log\":160,\"cpu\":0.15849899873137474,\"memory\":55.76},{\"round\":0,\"log\":161,\"cpu\":6.916044000536203,\"memory\":62.66},{\"round\":0,\"log\":162,\"cpu\":0.07517999969422817,\"memory\":62.69},{\"round\":0,\"log\":163,\"cpu\":7.5552699994295835,\"memory\":60.84},{\"round\":0,\"log\":164,\"cpu\":0.1279700007289648,\"memory\":60.93},{\"round\":0,\"log\":165,\"cpu\":4.730355000123382,\"memory\":66.53},{\"round\":0,\"log\":166,\"cpu\":0.17214900068938732,\"memory\":66.71},{\"round\":0,\"log\":167,\"cpu\":8.211076999083161,\"memory\":65.1},{\"round\":0,\"log\":168,\"cpu\":0.14606999978423119,\"memory\":65.18},{\"round\":0,\"log\":169,\"cpu\":6.6483149994164705,\"memory\":72.09},{\"round\":0,\"log\":170,\"cpu\":0.07228000089526176,\"memory\":72.12},{\"round\":0,\"log\":171,\"cpu\":7.418710999190807,\"memory\":70.63},{\"round\":0,\"log\":172,\"cpu\":0.12224900163710117,\"memory\":70.72},{\"round\":0,\"log\":173,\"cpu\":5.06674399971962,\"memory\":76.32},{\"round\":0,\"log\":174,\"cpu\":2.2141079995781183,\"memory\":69.2},{\"round\":0,\"log\":175,\"cpu\":5.799760000780225,\"memory\":75.03},{\"round\":0,\"log\":176,\"cpu\":0.20386899821460247,\"memory\":75.11},{\"round\":0,\"log\":177,\"cpu\":8.759064000099897,\"memory\":74.44},{\"round\":0,\"log\":178,\"cpu\":0.11066000163555145,\"memory\":74.49},{\"round\":0,\"log\":179,\"cpu\":5.313411999493837,\"memory\":80.33},{\"round\":0,\"log\":180,\"cpu\":0.17558899894356728,\"memory\":80.5},{\"round\":0,\"log\":181,\"cpu\":7.006583001464605,\"memory\":78.69},{\"round\":0,\"log\":182,\"cpu\":0.301018999889493,\"memory\":79},{\"round\":0,\"log\":183,\"cpu\":5.881418999284506,\"memory\":85.01},{\"round\":0,\"log\":184,\"cpu\":0.1906690001487732,\"memory\":85.11},{\"round\":0,\"log\":185,\"cpu\":21.838336000218987,\"memory\":8.87},{\"round\":0,\"log\":186,\"cpu\":0.19028900004923344,\"memory\":8.93},{\"round\":0,\"log\":187,\"cpu\":5.14529399946332,\"memory\":14.78},{\"round\":0,\"log\":188,\"cpu\":0.14871899969875813,\"memory\":14.95},{\"round\":0,\"log\":189,\"cpu\":4.919724000617862,\"memory\":20.65},{\"round\":0,\"log\":190,\"cpu\":0.23867899924516678,\"memory\":20.96},{\"round\":0,\"log\":191,\"cpu\":7.291042000055313,\"memory\":17.45},{\"round\":0,\"log\":192,\"cpu\":7.11455300077796,\"memory\":21.08},{\"round\":0,\"log\":193,\"cpu\":9.019602999091148,\"memory\":16.29},{\"round\":0,\"log\":194,\"cpu\":0.33669800125062466,\"memory\":16.4},{\"round\":0,\"log\":195,\"cpu\":0.22944900020956993,\"memory\":16.5},{\"round\":0,\"log\":196,\"cpu\":0.22184900008141994,\"memory\":16.6},{\"round\":0,\"log\":197,\"cpu\":0.25058799982070923,\"memory\":16.72},{\"round\":0,\"log\":198,\"cpu\":0.21104899980127811,\"memory\":16.82},{\"round\":0,\"log\":199,\"cpu\":112.1912049986422,\"memory\":65.12},{\"round\":0,\"log\":200,\"cpu\":0.06287000142037868,\"memory\":65.12},{\"round\":0,\"log\":201,\"cpu\":43.541232999414206,\"memory\":72.02},{\"round\":0,\"log\":202,\"cpu\":0.06333900056779385,\"memory\":72.02},{\"round\":0,\"log\":203,\"cpu\":3.7100409995764494,\"memory\":75.11},{\"round\":0,\"log\":204,\"cpu\":8.528465999290347,\"memory\":73.89},{\"round\":0,\"log\":205,\"cpu\":1.2037840001285076,\"memory\":75.06},{\"round\":0,\"log\":206,\"cpu\":3.0983030013740063,\"memory\":78.08},{\"round\":0,\"log\":207,\"cpu\":0.5287669990211725,\"memory\":78.66},{\"round\":0,\"log\":208,\"cpu\":5.710051000118256,\"memory\":70.92},{\"round\":0,\"log\":209,\"cpu\":0.8142949994653463,\"memory\":71.71},{\"round\":0,\"log\":210,\"cpu\":2.1915790010243654,\"memory\":73.76},{\"round\":0,\"log\":211,\"cpu\":6.138737998902798,\"memory\":80.18},{\"round\":0,\"log\":212,\"cpu\":1.0308149997144938,\"memory\":81.34},{\"round\":0,\"log\":213,\"cpu\":3.1763430014252663,\"memory\":69.65},{\"round\":0,\"log\":214,\"cpu\":0.6757069993764162,\"memory\":70.23},{\"round\":0,\"log\":215,\"cpu\":3.7293599992990494,\"memory\":74.31},{\"round\":0,\"log\":216,\"cpu\":0.728116000071168,\"memory\":75.11},{\"round\":0,\"log\":217,\"cpu\":1.8712310008704662,\"memory\":77.25},{\"round\":0,\"log\":218,\"cpu\":0.3835979998111725,\"memory\":77.65},{\"round\":0,\"log\":219,\"cpu\":6.058197999373078,\"memory\":70.78},{\"round\":0,\"log\":220,\"cpu\":1.7795910015702248,\"memory\":72.47},{\"round\":0,\"log\":221,\"cpu\":3.655460998415947,\"memory\":76.67},{\"round\":0,\"log\":222,\"cpu\":0.6740460004657507,\"memory\":77.42},{\"round\":0,\"log\":223,\"cpu\":4.302248001098633,\"memory\":82.1},{\"round\":0,\"log\":224,\"cpu\":1.4475919995456934,\"memory\":83.29},{\"round\":0,\"log\":225,\"cpu\":3.499251998960972,\"memory\":72.47},{\"round\":0,\"log\":226,\"cpu\":0.5318769998848438,\"memory\":73.01},{\"round\":0,\"log\":227,\"cpu\":5.629681000486016,\"memory\":79.44},{\"round\":0,\"log\":228,\"cpu\":1.9042499996721745,\"memory\":81.22},{\"round\":0,\"log\":229,\"cpu\":5.188673000782728,\"memory\":73.16},{\"round\":0,\"log\":230,\"cpu\":0.7410860005766153,\"memory\":74},{\"round\":0,\"log\":231,\"cpu\":4.156578999012709,\"memory\":78.68},{\"round\":0,\"log\":232,\"cpu\":1.4051319994032383,\"memory\":79.93},{\"round\":0,\"log\":233,\"cpu\":2.816925000399351,\"memory\":82.8},{\"round\":0,\"log\":234,\"cpu\":0.5793370008468628,\"memory\":83.39},{\"round\":0,\"log\":235,\"cpu\":6.21161799877882,\"memory\":75.16},{\"round\":0,\"log\":236,\"cpu\":0.11611900106072426,\"memory\":75.21},{\"round\":0,\"log\":237,\"cpu\":4.080519000068307,\"memory\":79.34},{\"round\":0,\"log\":238,\"cpu\":0.058729998767375946,\"memory\":79.37},{\"round\":0,\"log\":239,\"cpu\":4.911444000899792,\"memory\":71.45},{\"round\":0,\"log\":240,\"cpu\":0.10022000037133694,\"memory\":71.49},{\"round\":0,\"log\":241,\"cpu\":2.549406999722123,\"memory\":74.31},{\"round\":0,\"log\":242,\"cpu\":0.0522489994764328,\"memory\":74.32},{\"round\":0,\"log\":243,\"cpu\":5.374161999672651,\"memory\":80.74},{\"round\":0,\"log\":244,\"cpu\":0.13931900076568127,\"memory\":80.83},{\"round\":0,\"log\":245,\"cpu\":4.608745999634266,\"memory\":72.76},{\"round\":0,\"log\":246,\"cpu\":0.09442000091075897,\"memory\":72.81},{\"round\":0,\"log\":247,\"cpu\":4.142028000205755,\"memory\":77.44},{\"round\":0,\"log\":248,\"cpu\":0.14429999887943268,\"memory\":77.51},{\"round\":0,\"log\":249,\"cpu\":2.6358160004019737,\"memory\":80.3},{\"round\":0,\"log\":250,\"cpu\":0.07380899973213673,\"memory\":80.34},{\"round\":0,\"log\":251,\"cpu\":6.245427999645472,\"memory\":73.29},{\"round\":0,\"log\":252,\"cpu\":0.22678900137543678,\"memory\":73.46},{\"round\":0,\"log\":253,\"cpu\":3.722519999369979,\"memory\":77.48},{\"round\":0,\"log\":254,\"cpu\":0.12808999978005886,\"memory\":77.57},{\"round\":0,\"log\":255,\"cpu\":4.260297000408173,\"memory\":82.16},{\"round\":0,\"log\":256,\"cpu\":0.16664000041782856,\"memory\":82.28},{\"round\":0,\"log\":257,\"cpu\":3.2619519997388124,\"memory\":71.33},{\"round\":0,\"log\":258,\"cpu\":0.10769999958574772,\"memory\":71.39},{\"round\":0,\"log\":259,\"cpu\":5.297461999580264,\"memory\":77.76},{\"round\":0,\"log\":260,\"cpu\":0.34479800052940845,\"memory\":78.09},{\"round\":0,\"log\":261,\"cpu\":3.485121998935938,\"memory\":81.97},{\"round\":0,\"log\":262,\"cpu\":0.20342900045216084,\"memory\":82.12},{\"round\":0,\"log\":263,\"cpu\":5.101332999765873,\"memory\":72.51},{\"round\":0,\"log\":264,\"cpu\":0.285308999940753,\"memory\":72.74},{\"round\":0,\"log\":265,\"cpu\":2.2977780010551214,\"memory\":75.38},{\"round\":0,\"log\":266,\"cpu\":0.14257000014185905,\"memory\":75.49},{\"round\":0,\"log\":267,\"cpu\":5.556319998577237,\"memory\":81.82},{\"round\":0,\"log\":268,\"cpu\":0.0736600011587143,\"memory\":81.84},{\"round\":0,\"log\":269,\"cpu\":4.971704000607133,\"memory\":73.51},{\"round\":0,\"log\":270,\"cpu\":0.04340999945998192,\"memory\":73.52},{\"round\":0,\"log\":271,\"cpu\":3.9786890000104904,\"memory\":78.18},{\"round\":0,\"log\":272,\"cpu\":0.0560699999332428,\"memory\":78.21},{\"round\":0,\"log\":273,\"cpu\":2.6382759995758533,\"memory\":81.04},{\"round\":0,\"log\":274,\"cpu\":0.040629999712109566,\"memory\":81.06},{\"round\":0,\"log\":275,\"cpu\":6.530146000906825,\"memory\":73.73},{\"round\":0,\"log\":276,\"cpu\":0.07228999957442284,\"memory\":73.76},{\"round\":0,\"log\":277,\"cpu\":3.7835799995809793,\"memory\":77.93},{\"round\":0,\"log\":278,\"cpu\":0.05014999955892563,\"memory\":77.95},{\"round\":0,\"log\":279,\"cpu\":4.4723960012197495,\"memory\":82.6},{\"round\":0,\"log\":280,\"cpu\":0.06919999979436398,\"memory\":82.63},{\"round\":0,\"log\":281,\"cpu\":3.5463209990411997,\"memory\":71.77},{\"round\":0,\"log\":282,\"cpu\":0.04902000166475773,\"memory\":71.78},{\"round\":0,\"log\":283,\"cpu\":5.227702999487519,\"memory\":78.2},{\"round\":0,\"log\":284,\"cpu\":0.08517899923026562,\"memory\":78.25},{\"round\":0,\"log\":285,\"cpu\":3.771901000291109,\"memory\":82.41},{\"round\":0,\"log\":286,\"cpu\":0.058289000764489174,\"memory\":82.43},{\"round\":0,\"log\":287,\"cpu\":4.996874999254942,\"memory\":73.11},{\"round\":0,\"log\":288,\"cpu\":0.08441900089383125,\"memory\":73.15},{\"round\":0,\"log\":289,\"cpu\":2.4583969991654158,\"memory\":75.99},{\"round\":0,\"log\":290,\"cpu\":0.055460000410676,\"memory\":76.01},{\"round\":0,\"log\":291,\"cpu\":5.6538599990308285,\"memory\":82.43},{\"round\":0,\"log\":292,\"cpu\":0.15521899983286858,\"memory\":82.5},{\"round\":0,\"log\":293,\"cpu\":4.774866001680493,\"memory\":73.86},{\"round\":0,\"log\":294,\"cpu\":0.07575899921357632,\"memory\":73.89},{\"round\":0,\"log\":295,\"cpu\":3.923469999805093,\"memory\":78.54},{\"round\":0,\"log\":296,\"cpu\":0.10855899937450886,\"memory\":78.61},{\"round\":0,\"log\":297,\"cpu\":2.7153760008513927,\"memory\":81.45},{\"round\":0,\"log\":298,\"cpu\":0.07389000058174133,\"memory\":81.48},{\"round\":0,\"log\":299,\"cpu\":6.037977999076247,\"memory\":70.21},{\"round\":0,\"log\":300,\"cpu\":0.22251900099217892,\"memory\":70.3},{\"round\":0,\"log\":301,\"cpu\":0.1749889999628067,\"memory\":70.38},{\"round\":0,\"log\":302,\"cpu\":0.29500899836421013,\"memory\":70.52},{\"round\":0,\"log\":303,\"cpu\":0.27781799994409084,\"memory\":70.66},{\"round\":0,\"log\":304,\"cpu\":0.6310870014131069,\"memory\":70.92},{\"round\":0,\"log\":305,\"cpu\":0.4893479999154806,\"memory\":71.18},{\"round\":0,\"log\":306,\"cpu\":1.0621639993041754,\"memory\":71.72},{\"round\":0,\"log\":307,\"cpu\":0.19553899951279163,\"memory\":71.84},{\"round\":0,\"log\":308,\"cpu\":4.73199500143528,\"memory\":76.94},{\"round\":0,\"log\":309,\"cpu\":1.8951899986714125,\"memory\":78.69},{\"round\":0,\"log\":310,\"cpu\":6.660005001351237,\"memory\":73.61},{\"round\":0,\"log\":311,\"cpu\":1.1396039985120296,\"memory\":74.63},{\"round\":0,\"log\":312,\"cpu\":3.7877510003745556,\"memory\":79.45},{\"round\":0,\"log\":313,\"cpu\":0.7169960010796785,\"memory\":80.36},{\"round\":0,\"log\":314,\"cpu\":6.099747998639941,\"memory\":77.96},{\"round\":0,\"log\":315,\"cpu\":0.9708350002765656,\"memory\":78.85},{\"round\":0,\"log\":316,\"cpu\":18.268135000020266,\"memory\":89.54},{\"round\":0,\"log\":317,\"cpu\":11.242791000753641,\"memory\":90.43},{\"round\":0,\"log\":318,\"cpu\":2.0137799996882677,\"memory\":92.18},{\"round\":0,\"log\":319,\"cpu\":6.875994000583887,\"memory\":89.62},{\"round\":0,\"log\":320,\"cpu\":0.9720649998635054,\"memory\":90.64},{\"round\":0,\"log\":321,\"cpu\":4.26460799947381,\"memory\":95.47},{\"round\":0,\"log\":322,\"cpu\":0.8380549997091293,\"memory\":96.37},{\"round\":0,\"log\":323,\"cpu\":6.155238000676036,\"memory\":93.98},{\"round\":0,\"log\":324,\"cpu\":0.91461499966681,\"memory\":94.87},{\"round\":0,\"log\":325,\"cpu\":17.984657000750303,\"memory\":105.62},{\"round\":0,\"log\":326,\"cpu\":3.4458519984036684,\"memory\":108.49},{\"round\":0,\"log\":327,\"cpu\":7.447301000356674,\"memory\":106.33},{\"round\":0,\"log\":328,\"cpu\":6.585906000807881,\"memory\":109.9},{\"round\":0,\"log\":329,\"cpu\":8.34285599924624,\"memory\":107.53},{\"round\":0,\"log\":330,\"cpu\":1.6615120004862547,\"memory\":109.33},{\"round\":0,\"log\":331,\"cpu\":5.046883000060916,\"memory\":115.17},{\"round\":0,\"log\":332,\"cpu\":3.0375040005892515,\"memory\":107.73},{\"round\":0,\"log\":333,\"cpu\":19.38144899904728,\"memory\":10.41},{\"round\":0,\"log\":334,\"cpu\":0.9685450010001659,\"memory\":11.67},{\"round\":0,\"log\":335,\"cpu\":5.768349999561906,\"memory\":17.68},{\"round\":0,\"log\":336,\"cpu\":0.11257899925112724,\"memory\":17.77},{\"round\":0,\"log\":337,\"cpu\":8.03493900038302,\"memory\":14.45},{\"round\":0,\"log\":338,\"cpu\":0.05899900011718273,\"memory\":14.47},{\"round\":0,\"log\":339,\"cpu\":4.9747240003198385,\"memory\":20.32},{\"round\":0,\"log\":340,\"cpu\":0.04818999953567982,\"memory\":20.34},{\"round\":0,\"log\":341,\"cpu\":6.539486000314355,\"memory\":19.33},{\"round\":0,\"log\":342,\"cpu\":0.05374999903142452,\"memory\":19.35},{\"round\":0,\"log\":343,\"cpu\":5.981219001114368,\"memory\":25.35},{\"round\":0,\"log\":344,\"cpu\":0.10199899971485138,\"memory\":25.44},{\"round\":0,\"log\":345,\"cpu\":8.105476999655366,\"memory\":24.3},{\"round\":0,\"log\":346,\"cpu\":0.060590000823140144,\"memory\":24.32},{\"round\":0,\"log\":347,\"cpu\":5.080613998696208,\"memory\":30.17},{\"round\":0,\"log\":348,\"cpu\":0.04829000122845173,\"memory\":30.19},{\"round\":0,\"log\":349,\"cpu\":6.475506000220776,\"memory\":28.5},{\"round\":0,\"log\":350,\"cpu\":0.05064000003039837,\"memory\":28.51},{\"round\":0,\"log\":351,\"cpu\":5.85805899836123,\"memory\":34.52},{\"round\":0,\"log\":352,\"cpu\":0.09727900102734566,\"memory\":34.6},{\"round\":0,\"log\":353,\"cpu\":8.402527000755072,\"memory\":34.4},{\"round\":0,\"log\":354,\"cpu\":0.06763899885118008,\"memory\":34.42},{\"round\":0,\"log\":355,\"cpu\":6.887174999341369,\"memory\":32.82},{\"round\":0,\"log\":356,\"cpu\":0.1460990011692047,\"memory\":32.91},{\"round\":0,\"log\":357,\"cpu\":4.7978050000965595,\"memory\":38.51},{\"round\":0,\"log\":358,\"cpu\":0.1995289996266365,\"memory\":38.69},{\"round\":0,\"log\":359,\"cpu\":7.206692000851035,\"memory\":37.18},{\"round\":0,\"log\":360,\"cpu\":0.1456989999860525,\"memory\":37.26},{\"round\":0,\"log\":361,\"cpu\":6.706404998898506,\"memory\":44.15},{\"round\":0,\"log\":362,\"cpu\":0.0647400002926588,\"memory\":44.18},{\"round\":0,\"log\":363,\"cpu\":7.1475329995155334,\"memory\":42.28},{\"round\":0,\"log\":364,\"cpu\":0.11864900030195713,\"memory\":42.38},{\"round\":0,\"log\":365,\"cpu\":4.817375000566244,\"memory\":47.98},{\"round\":0,\"log\":366,\"cpu\":0.20043900050222874,\"memory\":48.16},{\"round\":0,\"log\":367,\"cpu\":7.387630999088287,\"memory\":46.59},{\"round\":0,\"log\":368,\"cpu\":0.1592590007930994,\"memory\":46.67},{\"round\":0,\"log\":369,\"cpu\":6.640385998412967,\"memory\":53.57},{\"round\":0,\"log\":370,\"cpu\":0.09133000113070011,\"memory\":53.62},{\"round\":0,\"log\":371,\"cpu\":6.86260399967432,\"memory\":51.87},{\"round\":0,\"log\":372,\"cpu\":0.1727290004491806,\"memory\":52.04},{\"round\":0,\"log\":373,\"cpu\":4.884553998708725,\"memory\":57.73},{\"round\":0,\"log\":374,\"cpu\":0.26055900007486343,\"memory\":58.04},{\"round\":0,\"log\":375,\"cpu\":7.703220000490546,\"memory\":56.56},{\"round\":0,\"log\":376,\"cpu\":0.12114899978041649,\"memory\":56.65},{\"round\":0,\"log\":377,\"cpu\":8.624435000121593,\"memory\":56.11},{\"round\":0,\"log\":378,\"cpu\":0.08688000030815601,\"memory\":56.17},{\"round\":0,\"log\":379,\"cpu\":5.1331229992210865,\"memory\":62.01},{\"round\":0,\"log\":380,\"cpu\":0.14213900081813335,\"memory\":62.18},{\"round\":0,\"log\":381,\"cpu\":6.859174000099301,\"memory\":60.44},{\"round\":0,\"log\":382,\"cpu\":0.32043899968266487,\"memory\":60.76},{\"round\":0,\"log\":383,\"cpu\":5.904248999431729,\"memory\":66.76},{\"round\":0,\"log\":384,\"cpu\":8.49693600088358,\"memory\":61.77},{\"round\":0,\"log\":385,\"cpu\":6.870363999158144,\"memory\":65.34},{\"round\":0,\"log\":386,\"cpu\":0.16369900107383728,\"memory\":65.44},{\"round\":0,\"log\":387,\"cpu\":0.16040899977087975,\"memory\":65.54},{\"round\":0,\"log\":388,\"cpu\":0.14815899915993214,\"memory\":65.64},{\"round\":0,\"log\":389,\"cpu\":0.15902000106871128,\"memory\":65.76},{\"round\":0,\"log\":390,\"cpu\":0.12944900058209896,\"memory\":65.86},{\"round\":0,\"log\":391,\"cpu\":114.94150099903345,\"memory\":107.62},{\"round\":0,\"log\":392,\"cpu\":0.061240000650286674,\"memory\":107.62},{\"round\":0,\"log\":393,\"cpu\":54.57826500013471,\"memory\":60.88},{\"round\":0,\"log\":394,\"cpu\":0.0707899983972311,\"memory\":60.88},{\"round\":0,\"log\":395,\"cpu\":3.7714710012078285,\"memory\":63.97},{\"round\":0,\"log\":396,\"cpu\":7.486730000004172,\"memory\":63.09},{\"round\":0,\"log\":397,\"cpu\":1.240574000403285,\"memory\":64.24},{\"round\":0,\"log\":398,\"cpu\":2.7272359989583492,\"memory\":67.25},{\"round\":0,\"log\":399,\"cpu\":0.5721669998019934,\"memory\":67.83},{\"round\":0,\"log\":400,\"cpu\":5.037503000348806,\"memory\":59.79},{\"round\":0,\"log\":401,\"cpu\":1.0129850003868341,\"memory\":60.58},{\"round\":0,\"log\":402,\"cpu\":1.9658700004220009,\"memory\":62.62},{\"round\":0,\"log\":403,\"cpu\":5.821808999404311,\"memory\":69.04},{\"round\":0,\"log\":404,\"cpu\":1.0297950003296137,\"memory\":70.19},{\"round\":0,\"log\":405,\"cpu\":2.5605669990181923,\"memory\":73.2},{\"round\":0,\"log\":406,\"cpu\":1.2812630012631416,\"memory\":59.57},{\"round\":0,\"log\":407,\"cpu\":3.577250998467207,\"memory\":63.64},{\"round\":0,\"log\":408,\"cpu\":0.7289470005780458,\"memory\":64.44},{\"round\":0,\"log\":409,\"cpu\":1.7673899997025728,\"memory\":66.48},{\"round\":0,\"log\":410,\"cpu\":0.37998799979686737,\"memory\":66.87},{\"round\":0,\"log\":411,\"cpu\":5.259153001010418,\"memory\":72.89},{\"round\":0,\"log\":412,\"cpu\":2.6296570003032684,\"memory\":61.84},{\"round\":0,\"log\":413,\"cpu\":3.8018789999186993,\"memory\":66.03},{\"round\":0,\"log\":414,\"cpu\":0.6860469989478588,\"memory\":66.79},{\"round\":0,\"log\":415,\"cpu\":4.1438980009406805,\"memory\":71.45},{\"round\":0,\"log\":416,\"cpu\":1.3731730002909899,\"memory\":72.65},{\"round\":0,\"log\":417,\"cpu\":3.337992999702692,\"memory\":61.79},{\"round\":0,\"log\":418,\"cpu\":0.521976999938488,\"memory\":62.32},{\"round\":0,\"log\":419,\"cpu\":5.511640999466181,\"memory\":68.75},{\"round\":0,\"log\":420,\"cpu\":1.8069609999656677,\"memory\":70.53},{\"round\":0,\"log\":421,\"cpu\":4.934504000470042,\"memory\":62.8},{\"round\":0,\"log\":422,\"cpu\":0.7741359993815422,\"memory\":63.64},{\"round\":0,\"log\":423,\"cpu\":4.106939001008868,\"memory\":68.31},{\"round\":0,\"log\":424,\"cpu\":1.3803629986941814,\"memory\":69.56},{\"round\":0,\"log\":425,\"cpu\":2.6634360011667013,\"memory\":72.43},{\"round\":0,\"log\":426,\"cpu\":0.5695169996470213,\"memory\":73.02},{\"round\":0,\"log\":427,\"cpu\":6.1561179999262094,\"memory\":64.77},{\"round\":0,\"log\":428,\"cpu\":0.10611899942159653,\"memory\":64.83},{\"round\":0,\"log\":429,\"cpu\":3.958960000425577,\"memory\":68.95},{\"round\":0,\"log\":430,\"cpu\":0.05189900100231171,\"memory\":68.98},{\"round\":0,\"log\":431,\"cpu\":5.062553999945521,\"memory\":61.21},{\"round\":0,\"log\":432,\"cpu\":0.10276899859309196,\"memory\":61.26},{\"round\":0,\"log\":433,\"cpu\":2.586837001144886,\"memory\":64.07},{\"round\":0,\"log\":434,\"cpu\":0.047369999811053276,\"memory\":64.09},{\"round\":0,\"log\":435,\"cpu\":5.286661999300122,\"memory\":70.49},{\"round\":0,\"log\":436,\"cpu\":0.14421899989247322,\"memory\":70.59},{\"round\":0,\"log\":437,\"cpu\":4.897765001282096,\"memory\":62.6},{\"round\":0,\"log\":438,\"cpu\":0.09133999980986118,\"memory\":62.65},{\"round\":0,\"log\":439,\"cpu\":4.042527999728918,\"memory\":67.27},{\"round\":0,\"log\":440,\"cpu\":0.11696000024676323,\"memory\":67.34},{\"round\":0,\"log\":441,\"cpu\":2.6610959991812706,\"memory\":70.12},{\"round\":0,\"log\":442,\"cpu\":0.07283899933099747,\"memory\":70.16},{\"round\":0,\"log\":443,\"cpu\":6.26099800132215,\"memory\":63.18},{\"round\":0,\"log\":444,\"cpu\":0.2231189999729395,\"memory\":63.35},{\"round\":0,\"log\":445,\"cpu\":3.789349999278784,\"memory\":67.38},{\"round\":0,\"log\":446,\"cpu\":0.11985900066792965,\"memory\":67.46},{\"round\":0,\"log\":447,\"cpu\":4.267408000305295,\"memory\":72.04},{\"round\":0,\"log\":448,\"cpu\":0.16971899941563606,\"memory\":72.17},{\"round\":0,\"log\":449,\"cpu\":3.1800839994102716,\"memory\":61.26},{\"round\":0,\"log\":450,\"cpu\":0.12954900041222572,\"memory\":61.33},{\"round\":0,\"log\":451,\"cpu\":5.301442001014948,\"memory\":67.7},{\"round\":0,\"log\":452,\"cpu\":0.34422799944877625,\"memory\":68.02},{\"round\":0,\"log\":453,\"cpu\":3.490531999617815,\"memory\":71.9},{\"round\":0,\"log\":454,\"cpu\":0.19660899974405766,\"memory\":72.05},{\"round\":0,\"log\":455,\"cpu\":4.53256700001657,\"memory\":62.45},{\"round\":0,\"log\":456,\"cpu\":0.2849080003798008,\"memory\":62.68},{\"round\":0,\"log\":457,\"cpu\":2.2921680007129908,\"memory\":65.32},{\"round\":0,\"log\":458,\"cpu\":0.14637899957597256,\"memory\":65.43},{\"round\":0,\"log\":459,\"cpu\":5.520411999896169,\"memory\":71.75},{\"round\":0,\"log\":460,\"cpu\":0.0628689993172884,\"memory\":71.77},{\"round\":0,\"log\":461,\"cpu\":4.558197000995278,\"memory\":63.42},{\"round\":0,\"log\":462,\"cpu\":0.04291899874806404,\"memory\":63.44},{\"round\":0,\"log\":463,\"cpu\":3.9479300007224083,\"memory\":68.09},{\"round\":0,\"log\":464,\"cpu\":0.050418999046087265,\"memory\":68.11},{\"round\":0,\"log\":465,\"cpu\":2.604527000337839,\"memory\":70.94},{\"round\":0,\"log\":466,\"cpu\":0.03619999997317791,\"memory\":70.96},{\"round\":0,\"log\":467,\"cpu\":5.995959000661969,\"memory\":63.7},{\"round\":0,\"log\":468,\"cpu\":0.06412900052964687,\"memory\":63.73},{\"round\":0,\"log\":469,\"cpu\":3.5294119995087385,\"memory\":67.89},{\"round\":0,\"log\":470,\"cpu\":0.046800000593066216,\"memory\":67.91},{\"round\":0,\"log\":471,\"cpu\":4.325186999514699,\"memory\":72.56},{\"round\":0,\"log\":472,\"cpu\":0.05790000036358833,\"memory\":72.59},{\"round\":0,\"log\":473,\"cpu\":3.7695199996232986,\"memory\":61.73},{\"round\":0,\"log\":474,\"cpu\":0.04463000036776066,\"memory\":61.75},{\"round\":0,\"log\":475,\"cpu\":5.25501300022006,\"memory\":68.16},{\"round\":0,\"log\":476,\"cpu\":0.07566899992525578,\"memory\":68.2},{\"round\":0,\"log\":477,\"cpu\":3.6654109992086887,\"memory\":72.37},{\"round\":0,\"log\":478,\"cpu\":0.05134999938309193,\"memory\":72.39},{\"round\":0,\"log\":479,\"cpu\":4.784685000777245,\"memory\":63.07},{\"round\":0,\"log\":480,\"cpu\":0.07594900019466877,\"memory\":63.12},{\"round\":0,\"log\":481,\"cpu\":2.4293179996311665,\"memory\":65.95},{\"round\":0,\"log\":482,\"cpu\":0.052369000390172005,\"memory\":65.97},{\"round\":0,\"log\":483,\"cpu\":5.729899998754263,\"memory\":72.39},{\"round\":0,\"log\":484,\"cpu\":0.12471000105142593,\"memory\":72.46},{\"round\":0,\"log\":485,\"cpu\":4.8444250002503395,\"memory\":63.87},{\"round\":0,\"log\":486,\"cpu\":0.07370899990200996,\"memory\":63.9},{\"round\":0,\"log\":487,\"cpu\":3.8948599994182587,\"memory\":68.56},{\"round\":0,\"log\":488,\"cpu\":0.10997899994254112,\"memory\":68.62},{\"round\":0,\"log\":489,\"cpu\":2.5183870010077953,\"memory\":71.46},{\"round\":0,\"log\":490,\"cpu\":0.06526999920606613,\"memory\":71.49},{\"round\":0,\"log\":491,\"cpu\":5.707569999620318,\"memory\":60.26},{\"round\":0,\"log\":492,\"cpu\":0.22822900116443634,\"memory\":60.34},{\"round\":0,\"log\":493,\"cpu\":0.16809899918735027,\"memory\":60.42},{\"round\":0,\"log\":494,\"cpu\":0.3126790001988411,\"memory\":60.56},{\"round\":0,\"log\":495,\"cpu\":0.2957279998809099,\"memory\":60.7},{\"round\":0,\"log\":496,\"cpu\":0.4943870007991791,\"memory\":60.97},{\"round\":0,\"log\":497,\"cpu\":0.47135799936950207,\"memory\":61.23},{\"round\":0,\"log\":498,\"cpu\":1.001885000616312,\"memory\":61.76},{\"round\":0,\"log\":499,\"cpu\":0.238128999248147,\"memory\":61.88},{\"round\":0,\"log\":500,\"cpu\":4.824594000354409,\"memory\":67},{\"round\":0,\"log\":501,\"cpu\":1.8281609993427992,\"memory\":68.75},{\"round\":0,\"log\":502,\"cpu\":5.731650000438094,\"memory\":63.63},{\"round\":0,\"log\":503,\"cpu\":0.9837849996984005,\"memory\":64.65},{\"round\":0,\"log\":504,\"cpu\":3.821609999984503,\"memory\":69.49},{\"round\":0,\"log\":505,\"cpu\":0.7268160004168749,\"memory\":70.39},{\"round\":0,\"log\":506,\"cpu\":6.005339000374079,\"memory\":68.07},{\"round\":0,\"log\":507,\"cpu\":0.8429060000926256,\"memory\":68.96},{\"round\":0,\"log\":508,\"cpu\":18.048674998804927,\"memory\":79.61},{\"round\":0,\"log\":509,\"cpu\":10.644905000925064,\"memory\":80.46},{\"round\":0,\"log\":510,\"cpu\":2.0185189992189407,\"memory\":82.21},{\"round\":0,\"log\":511,\"cpu\":6.374117000028491,\"memory\":79.68},{\"round\":0,\"log\":512,\"cpu\":1.1292640008032322,\"memory\":80.69},{\"round\":0,\"log\":513,\"cpu\":4.560015998780727,\"memory\":85.52},{\"round\":0,\"log\":514,\"cpu\":0.9086960013955832,\"memory\":86.43},{\"round\":0,\"log\":515,\"cpu\":5.631939999759197,\"memory\":84.02},{\"round\":0,\"log\":516,\"cpu\":0.9327149987220764,\"memory\":84.91},{\"round\":0,\"log\":517,\"cpu\":17.359390001744032,\"memory\":95.74},{\"round\":0,\"log\":518,\"cpu\":3.6966509986668825,\"memory\":98.6},{\"round\":0,\"log\":519,\"cpu\":7.393481001257896,\"memory\":96.48},{\"round\":0,\"log\":520,\"cpu\":6.50271699950099,\"memory\":100.03},{\"round\":0,\"log\":521,\"cpu\":8.515364998951554,\"memory\":97.7},{\"round\":0,\"log\":522,\"cpu\":1.7901710011065006,\"memory\":99.5},{\"round\":0,\"log\":523,\"cpu\":5.21000299975276,\"memory\":105.34},{\"round\":0,\"log\":524,\"cpu\":2.8241050001233816,\"memory\":97.87},{\"round\":0,\"log\":525,\"cpu\":5.146982999518514,\"memory\":103.56},{\"round\":0,\"log\":526,\"cpu\":0.8576459996402264,\"memory\":104.82},{\"round\":0,\"log\":527,\"cpu\":7.834878999739885,\"memory\":102.73},{\"round\":0,\"log\":528,\"cpu\":0.11428900063037872,\"memory\":102.82},{\"round\":0,\"log\":529,\"cpu\":6.572656000033021,\"memory\":109.72},{\"round\":0,\"log\":530,\"cpu\":0.05678999982774258,\"memory\":109.74},{\"round\":0,\"log\":531,\"cpu\":7.255561999976635,\"memory\":107.65},{\"round\":0,\"log\":532,\"cpu\":0.05386999994516373,\"memory\":107.66},{\"round\":0,\"log\":533,\"cpu\":4.825583999976516,\"memory\":113.36},{\"round\":0,\"log\":534,\"cpu\":0.048500001430511475,\"memory\":113.37},{\"round\":0,\"log\":535,\"cpu\":7.849688999354839,\"memory\":112.08},{\"round\":0,\"log\":536,\"cpu\":0.11212899908423424,\"memory\":112.17},{\"round\":0,\"log\":537,\"cpu\":6.461347000673413,\"memory\":119.07},{\"round\":0,\"log\":538,\"cpu\":0.05526000075042248,\"memory\":119.09},{\"round\":0,\"log\":539,\"cpu\":6.94561299867928,\"memory\":117.18},{\"round\":0,\"log\":540,\"cpu\":0.05171000026166439,\"memory\":117.2},{\"round\":0,\"log\":541,\"cpu\":4.705355999991298,\"memory\":122.89},{\"round\":0,\"log\":542,\"cpu\":0.04575899988412857,\"memory\":122.9},{\"round\":0,\"log\":543,\"cpu\":7.691130001097918,\"memory\":121.55},{\"round\":0,\"log\":544,\"cpu\":0.11349999904632568,\"memory\":121.63},{\"round\":0,\"log\":545,\"cpu\":8.528024999424815,\"memory\":121.27},{\"round\":0,\"log\":546,\"cpu\":0.06995999999344349,\"memory\":121.3},{\"round\":0,\"log\":547,\"cpu\":5.146423000842333,\"memory\":127.12},{\"round\":0,\"log\":548,\"cpu\":0.10755899921059608,\"memory\":127.21},{\"round\":0,\"log\":549,\"cpu\":6.660096000880003,\"memory\":125.51},{\"round\":0,\"log\":550,\"cpu\":0.2023290004581213,\"memory\":125.69},{\"round\":0,\"log\":551,\"cpu\":5.794329999014735,\"memory\":131.52},{\"round\":0,\"log\":552,\"cpu\":0.10537900030612946,\"memory\":131.6},{\"round\":0,\"log\":553,\"cpu\":8.367035999894142,\"memory\":130.8},{\"round\":0,\"log\":554,\"cpu\":0.0774300005286932,\"memory\":130.83},{\"round\":0,\"log\":555,\"cpu\":5.180232999846339,\"memory\":136.66},{\"round\":0,\"log\":556,\"cpu\":0.10838999971747398,\"memory\":136.76},{\"round\":0,\"log\":557,\"cpu\":6.892753999680281,\"memory\":134.86},{\"round\":0,\"log\":558,\"cpu\":0.17737900093197823,\"memory\":135.04},{\"round\":0,\"log\":559,\"cpu\":5.7641690000891685,\"memory\":140.87},{\"round\":0,\"log\":560,\"cpu\":0.12838999927043915,\"memory\":140.96},{\"round\":0,\"log\":561,\"cpu\":8.570004999637604,\"memory\":140.24},{\"round\":0,\"log\":562,\"cpu\":0.10594999976456165,\"memory\":140.29},{\"round\":0,\"log\":563,\"cpu\":5.031274000182748,\"memory\":146.13},{\"round\":0,\"log\":564,\"cpu\":0.15675900131464005,\"memory\":146.29},{\"round\":0,\"log\":565,\"cpu\":6.932852998375893,\"memory\":144.41},{\"round\":0,\"log\":566,\"cpu\":0.29698900133371353,\"memory\":144.73},{\"round\":0,\"log\":567,\"cpu\":5.957549000158906,\"memory\":150.73},{\"round\":0,\"log\":568,\"cpu\":0.12051899917423725,\"memory\":150.83},{\"round\":0,\"log\":569,\"cpu\":8.573055999353528,\"memory\":150.73},{\"round\":0,\"log\":570,\"cpu\":0.10179900005459785,\"memory\":150.79},{\"round\":0,\"log\":571,\"cpu\":7.246072001755238,\"memory\":149.02},{\"round\":0,\"log\":572,\"cpu\":0.18841899931430817,\"memory\":149.18},{\"round\":0,\"log\":573,\"cpu\":4.975143998861313,\"memory\":154.87},{\"round\":0,\"log\":574,\"cpu\":0.26082900166511536,\"memory\":155.19},{\"round\":0,\"log\":575,\"cpu\":7.814798999577761,\"memory\":153.56},{\"round\":0,\"log\":576,\"cpu\":6.717365000396967,\"memory\":157.1},{\"round\":0,\"log\":577,\"cpu\":6.558495998382568,\"memory\":160.66},{\"round\":0,\"log\":578,\"cpu\":0.15865000151097775,\"memory\":160.77},{\"round\":0,\"log\":579,\"cpu\":0.1492689996957779,\"memory\":160.87},{\"round\":0,\"log\":580,\"cpu\":0.22515900060534477,\"memory\":160.97},{\"round\":0,\"log\":581,\"cpu\":0.17199899815022945,\"memory\":161.08},{\"round\":0,\"log\":582,\"cpu\":0.13648900017142296,\"memory\":161.19},{\"round\":0,\"log\":583,\"cpu\":115.77598700113595,\"memory\":200.91},{\"round\":0,\"log\":584,\"cpu\":0.06189899891614914,\"memory\":200.92},{\"round\":0,\"log\":585,\"cpu\":45.51726300083101,\"memory\":207.52},{\"round\":0,\"log\":586,\"cpu\":0.062130000442266464,\"memory\":207.52},{\"round\":0,\"log\":587,\"cpu\":3.5777009986341,\"memory\":210.4},{\"round\":0,\"log\":588,\"cpu\":7.973379001021385,\"memory\":209.7},{\"round\":0,\"log\":589,\"cpu\":1.208822999149561,\"memory\":210.86},{\"round\":0,\"log\":590,\"cpu\":2.815845001488924,\"memory\":213.87},{\"round\":0,\"log\":591,\"cpu\":0.5964269991964102,\"memory\":214.45},{\"round\":0,\"log\":592,\"cpu\":3.893570000305772,\"memory\":218.52},{\"round\":0,\"log\":593,\"cpu\":0.8354049995541573,\"memory\":219.31},{\"round\":0,\"log\":594,\"cpu\":2.5910870004445314,\"memory\":206.74},{\"round\":0,\"log\":595,\"cpu\":6.136057998985052,\"memory\":213.15},{\"round\":0,\"log\":596,\"cpu\":1.1725740004330873,\"memory\":214.31},{\"round\":0,\"log\":597,\"cpu\":2.564547000452876,\"memory\":217.32},{\"round\":0,\"log\":598,\"cpu\":0.5191670004278421,\"memory\":217.89},{\"round\":0,\"log\":599,\"cpu\":4.246647998690605,\"memory\":207.51},{\"round\":0,\"log\":600,\"cpu\":0.8569649998098612,\"memory\":208.3},{\"round\":0,\"log\":601,\"cpu\":1.7671110015362501,\"memory\":210.34},{\"round\":0,\"log\":602,\"cpu\":0.38205800019204617,\"memory\":210.74},{\"round\":0,\"log\":603,\"cpu\":4.958543999120593,\"memory\":216.75},{\"round\":0,\"log\":604,\"cpu\":1.5294620003551245,\"memory\":218.44},{\"round\":0,\"log\":605,\"cpu\":4.7807959988713264,\"memory\":210.28},{\"round\":0,\"log\":606,\"cpu\":0.6792560014873743,\"memory\":211.03},{\"round\":0,\"log\":607,\"cpu\":4.014888999983668,\"memory\":215.7},{\"round\":0,\"log\":608,\"cpu\":1.2137039992958307,\"memory\":216.89},{\"round\":0,\"log\":609,\"cpu\":2.710155000910163,\"memory\":219.75},{\"round\":0,\"log\":610,\"cpu\":0.5945669990032911,\"memory\":220.29},{\"round\":0,\"log\":611,\"cpu\":6.14329900033772,\"memory\":212.07},{\"round\":0,\"log\":612,\"cpu\":1.8049899991601706,\"memory\":213.85},{\"round\":0,\"log\":613,\"cpu\":3.9282400012016296,\"memory\":218.04},{\"round\":0,\"log\":614,\"cpu\":0.7381259985268116,\"memory\":218.88},{\"round\":0,\"log\":615,\"cpu\":4.937494000419974,\"memory\":209.8},{\"round\":0,\"log\":616,\"cpu\":1.2400240004062653,\"memory\":211.06},{\"round\":0,\"log\":617,\"cpu\":2.476935999467969,\"memory\":213.92},{\"round\":0,\"log\":618,\"cpu\":0.5643570013344288,\"memory\":214.51},{\"round\":0,\"log\":619,\"cpu\":7.011903999373317,\"memory\":208.97},{\"round\":0,\"log\":620,\"cpu\":0.11008000001311302,\"memory\":209.02},{\"round\":0,\"log\":621,\"cpu\":3.59651100076735,\"memory\":213.15},{\"round\":0,\"log\":622,\"cpu\":0.05200899951159954,\"memory\":213.17},{\"round\":0,\"log\":623,\"cpu\":4.076748998835683,\"memory\":217.81},{\"round\":0,\"log\":624,\"cpu\":0.08596000075340271,\"memory\":217.86},{\"round\":0,\"log\":625,\"cpu\":3.275492999702692,\"memory\":207.76},{\"round\":0,\"log\":626,\"cpu\":0.05465899966657162,\"memory\":207.78},{\"round\":0,\"log\":627,\"cpu\":5.583982000127435,\"memory\":214.18},{\"round\":0,\"log\":628,\"cpu\":0.13199900090694427,\"memory\":214.28},{\"round\":0,\"log\":629,\"cpu\":3.7313499990850687,\"memory\":218.37},{\"round\":0,\"log\":630,\"cpu\":0.08296000026166439,\"memory\":218.42},{\"round\":0,\"log\":631,\"cpu\":5.148572999984026,\"memory\":209.46},{\"round\":0,\"log\":632,\"cpu\":0.12130900099873543,\"memory\":209.53},{\"round\":0,\"log\":633,\"cpu\":2.501266999170184,\"memory\":212.32},{\"round\":0,\"log\":634,\"cpu\":0.0731000006198883,\"memory\":212.36},{\"round\":0,\"log\":635,\"cpu\":5.644850999116898,\"memory\":218.75},{\"round\":0,\"log\":636,\"cpu\":0.1953389998525381,\"memory\":218.91},{\"round\":0,\"log\":637,\"cpu\":4.777195001021028,\"memory\":210.07},{\"round\":0,\"log\":638,\"cpu\":0.12394899874925613,\"memory\":210.15},{\"round\":0,\"log\":639,\"cpu\":3.8696100004017353,\"memory\":214.74},{\"round\":0,\"log\":640,\"cpu\":0.16026899963617325,\"memory\":214.86},{\"round\":0,\"log\":641,\"cpu\":2.6106770001351833,\"memory\":217.6},{\"round\":0,\"log\":642,\"cpu\":0.11299899965524673,\"memory\":217.66},{\"round\":0,\"log\":643,\"cpu\":6.793514000251889,\"memory\":210.44},{\"round\":0,\"log\":644,\"cpu\":0.40223800018429756,\"memory\":210.76},{\"round\":0,\"log\":645,\"cpu\":3.4672430008649826,\"memory\":214.63},{\"round\":0,\"log\":646,\"cpu\":0.2095589991658926,\"memory\":214.79},{\"round\":0,\"log\":647,\"cpu\":4.261597000062466,\"memory\":219.3},{\"round\":0,\"log\":648,\"cpu\":0.2731590010225773,\"memory\":219.54},{\"round\":0,\"log\":649,\"cpu\":3.3487119991332293,\"memory\":208.09},{\"round\":0,\"log\":650,\"cpu\":0.15450900048017502,\"memory\":208.21},{\"round\":0,\"log\":651,\"cpu\":5.158263999968767,\"memory\":214.53},{\"round\":0,\"log\":652,\"cpu\":0.05144899897277355,\"memory\":214.55},{\"round\":0,\"log\":653,\"cpu\":3.6508610006421804,\"memory\":218.72},{\"round\":0,\"log\":654,\"cpu\":0.037529999390244484,\"memory\":218.73},{\"round\":0,\"log\":655,\"cpu\":4.91130500100553,\"memory\":209.71},{\"round\":0,\"log\":656,\"cpu\":0.051138998940587044,\"memory\":209.73},{\"round\":0,\"log\":657,\"cpu\":2.4526370000094175,\"memory\":212.57},{\"round\":0,\"log\":658,\"cpu\":0.03586000017821789,\"memory\":212.58},{\"round\":0,\"log\":659,\"cpu\":5.64487100020051,\"memory\":218.99},{\"round\":0,\"log\":660,\"cpu\":0.06072000041604042,\"memory\":219.02},{\"round\":0,\"log\":661,\"cpu\":5.052622999995947,\"memory\":210.56},{\"round\":0,\"log\":662,\"cpu\":0.04464999958872795,\"memory\":210.58},{\"round\":0,\"log\":663,\"cpu\":3.8989000003784895,\"memory\":215.23},{\"round\":0,\"log\":664,\"cpu\":0.054169999435544014,\"memory\":215.26},{\"round\":0,\"log\":665,\"cpu\":2.6837850008159876,\"memory\":218.09},{\"round\":0,\"log\":666,\"cpu\":0.04088999889791012,\"memory\":218.11},{\"round\":0,\"log\":667,\"cpu\":6.242578001692891,\"memory\":210.79},{\"round\":0,\"log\":668,\"cpu\":0.0794689990580082,\"memory\":210.84},{\"round\":0,\"log\":669,\"cpu\":3.6484409999102354,\"memory\":215},{\"round\":0,\"log\":670,\"cpu\":0.05121999979019165,\"memory\":215.02},{\"round\":0,\"log\":671,\"cpu\":4.351978000253439,\"memory\":219.68},{\"round\":0,\"log\":672,\"cpu\":0.06938900053501129,\"memory\":219.72},{\"round\":0,\"log\":673,\"cpu\":3.66279099881649,\"memory\":208.82},{\"round\":0,\"log\":674,\"cpu\":0.05794900096952915,\"memory\":208.84},{\"round\":0,\"log\":675,\"cpu\":5.277512999251485,\"memory\":215.26},{\"round\":0,\"log\":676,\"cpu\":0.11316999979317188,\"memory\":215.33},{\"round\":0,\"log\":677,\"cpu\":3.6920900009572506,\"memory\":219.5},{\"round\":0,\"log\":678,\"cpu\":0.06574999913573265,\"memory\":219.53},{\"round\":0,\"log\":679,\"cpu\":4.816825000569224,\"memory\":210.18},{\"round\":0,\"log\":680,\"cpu\":0.1056089997291565,\"memory\":210.24},{\"round\":0,\"log\":681,\"cpu\":2.4617870002985,\"memory\":213.08},{\"round\":0,\"log\":682,\"cpu\":0.06347000040113926,\"memory\":213.11},{\"round\":0,\"log\":683,\"cpu\":4.407826999202371,\"memory\":216.06},{\"round\":0,\"log\":684,\"cpu\":0.19476900063455105,\"memory\":216.13},{\"round\":0,\"log\":685,\"cpu\":0.16354900039732456,\"memory\":216.21},{\"round\":0,\"log\":686,\"cpu\":0.27117899991571903,\"memory\":216.35},{\"round\":0,\"log\":687,\"cpu\":0.2601579986512661,\"memory\":216.49},{\"round\":0,\"log\":688,\"cpu\":0.4774980004876852,\"memory\":216.75},{\"round\":0,\"log\":689,\"cpu\":0.4693369995802641,\"memory\":217},{\"round\":0,\"log\":690,\"cpu\":0.9746850002557039,\"memory\":217.52},{\"round\":0,\"log\":691,\"cpu\":0.1955990009009838,\"memory\":217.65},{\"round\":0,\"log\":692,\"cpu\":5.998320000246167,\"memory\":209.34},{\"round\":0,\"log\":693,\"cpu\":1.721400000154972,\"memory\":211.09},{\"round\":0,\"log\":694,\"cpu\":4.215187998488545,\"memory\":216.23},{\"round\":0,\"log\":695,\"cpu\":0.932056000456214,\"memory\":217.24},{\"round\":0,\"log\":696,\"cpu\":6.398415999487042,\"memory\":213.45},{\"round\":0,\"log\":697,\"cpu\":0.932065000757575,\"memory\":214.36},{\"round\":0,\"log\":698,\"cpu\":3.8733000010252,\"memory\":219.15},{\"round\":0,\"log\":699,\"cpu\":0.722435999661684,\"memory\":220.04},{\"round\":0,\"log\":700,\"cpu\":20.229724999517202,\"memory\":224.54},{\"round\":0,\"log\":701,\"cpu\":11.36417100019753,\"memory\":225.02},{\"round\":0,\"log\":702,\"cpu\":2.063808999955654,\"memory\":226.77},{\"round\":0,\"log\":703,\"cpu\":4.851885000243783,\"memory\":231.9},{\"round\":0,\"log\":704,\"cpu\":1.0473039988428354,\"memory\":232.92},{\"round\":0,\"log\":705,\"cpu\":6.312618000432849,\"memory\":229.49},{\"round\":0,\"log\":706,\"cpu\":0.9268950000405312,\"memory\":230.4},{\"round\":0,\"log\":707,\"cpu\":3.8403300009667873,\"memory\":235.18},{\"round\":0,\"log\":708,\"cpu\":0.7876059990376234,\"memory\":236.07},{\"round\":0,\"log\":709,\"cpu\":20.689611999318004,\"memory\":240.77},{\"round\":0,\"log\":710,\"cpu\":3.756520001217723,\"memory\":243.63},{\"round\":0,\"log\":711,\"cpu\":7.121283000335097,\"memory\":241.19},{\"round\":0,\"log\":712,\"cpu\":7.004803998395801,\"memory\":244.73},{\"round\":0,\"log\":713,\"cpu\":6.9381830003112555,\"memory\":251.63},{\"round\":0,\"log\":714,\"cpu\":3.466312000527978,\"memory\":243.67},{\"round\":0,\"log\":715,\"cpu\":5.37215300090611,\"memory\":249.52},{\"round\":0,\"log\":716,\"cpu\":0.9861439988017082,\"memory\":250.96},{\"round\":0,\"log\":717,\"cpu\":6.722915001213551,\"memory\":247.74},{\"round\":0,\"log\":718,\"cpu\":0.8919049985706806,\"memory\":249},{\"round\":0,\"log\":719,\"cpu\":5.901690000668168,\"memory\":255},{\"round\":0,\"log\":720,\"cpu\":0.10888000018894672,\"memory\":255.09},{\"round\":0,\"log\":721,\"cpu\":8.561514999717474,\"memory\":253.37},{\"round\":0,\"log\":722,\"cpu\":0.06438899971544743,\"memory\":253.39},{\"round\":0,\"log\":723,\"cpu\":4.922144999727607,\"memory\":259.23},{\"round\":0,\"log\":724,\"cpu\":0.04901000112295151,\"memory\":259.25},{\"round\":0,\"log\":725,\"cpu\":6.796733999624848,\"memory\":257.35},{\"round\":0,\"log\":726,\"cpu\":0.05300999991595745,\"memory\":257.36},{\"round\":0,\"log\":727,\"cpu\":5.983679000288248,\"memory\":263.37},{\"round\":0,\"log\":728,\"cpu\":0.09747899882495403,\"memory\":263.45},{\"round\":0,\"log\":729,\"cpu\":8.684545001015067,\"memory\":263.04},{\"round\":0,\"log\":730,\"cpu\":0.05855900049209595,\"memory\":263.06},{\"round\":0,\"log\":731,\"cpu\":5.2906329985708,\"memory\":268.9},{\"round\":0,\"log\":732,\"cpu\":0.05940000154078007,\"memory\":268.92},{\"round\":0,\"log\":733,\"cpu\":7.307071998715401,\"memory\":267.31},{\"round\":0,\"log\":734,\"cpu\":0.05075000040233135,\"memory\":267.32},{\"round\":0,\"log\":735,\"cpu\":7.998477999120951,\"memory\":266.17},{\"round\":0,\"log\":736,\"cpu\":0.11322900094091892,\"memory\":266.25},{\"round\":0,\"log\":737,\"cpu\":6.633576000109315,\"memory\":273.15},{\"round\":0,\"log\":738,\"cpu\":0.061048999428749084,\"memory\":273.18},{\"round\":0,\"log\":739,\"cpu\":7.307671999558806,\"memory\":271.23},{\"round\":0,\"log\":740,\"cpu\":0.14088000170886517,\"memory\":271.32},{\"round\":0,\"log\":741,\"cpu\":4.955713998526335,\"memory\":276.92},{\"round\":0,\"log\":742,\"cpu\":0.17682900093495846,\"memory\":277.1},{\"round\":0,\"log\":743,\"cpu\":7.7922089993953705,\"memory\":275.56},{\"round\":0,\"log\":744,\"cpu\":0.13102900050580502,\"memory\":275.64},{\"round\":0,\"log\":745,\"cpu\":6.65854600071907,\"memory\":282.54},{\"round\":0,\"log\":746,\"cpu\":0.06206999905407429,\"memory\":282.57},{\"round\":0,\"log\":747,\"cpu\":34.63742900080979,\"memory\":7.9},{\"round\":0,\"log\":748,\"cpu\":0.16646899841725826,\"memory\":7.99},{\"round\":0,\"log\":749,\"cpu\":4.826094999909401,\"memory\":13.61},{\"round\":0,\"log\":750,\"cpu\":0.17417900077998638,\"memory\":13.8},{\"round\":0,\"log\":751,\"cpu\":5.723449999466538,\"memory\":19.64},{\"round\":0,\"log\":752,\"cpu\":0.16648000106215477,\"memory\":19.74},{\"round\":0,\"log\":753,\"cpu\":7.380210999399424,\"memory\":14.3},{\"round\":0,\"log\":754,\"cpu\":0.1047189999371767,\"memory\":14.36},{\"round\":0,\"log\":755,\"cpu\":4.81814599968493,\"memory\":20.21},{\"round\":0,\"log\":756,\"cpu\":0.1425390001386404,\"memory\":20.38},{\"round\":0,\"log\":757,\"cpu\":5.698100000619888,\"memory\":13.85},{\"round\":0,\"log\":758,\"cpu\":0.24910899996757507,\"memory\":14.17},{\"round\":0,\"log\":759,\"cpu\":5.796439999714494,\"memory\":20.18},{\"round\":0,\"log\":760,\"cpu\":0.13527899980545044,\"memory\":20.29},{\"round\":0,\"log\":761,\"cpu\":7.144712999463081,\"memory\":14.09},{\"round\":0,\"log\":762,\"cpu\":0.09219900146126747,\"memory\":14.15},{\"round\":0,\"log\":763,\"cpu\":5.0658339988440275,\"memory\":20},{\"round\":0,\"log\":764,\"cpu\":0.16060900129377842,\"memory\":20.16},{\"round\":0,\"log\":765,\"cpu\":5.596460999920964,\"memory\":13.32},{\"round\":0,\"log\":766,\"cpu\":0.24595899879932404,\"memory\":13.64},{\"round\":0,\"log\":767,\"cpu\":5.924139000475407,\"memory\":19.64},{\"round\":0,\"log\":768,\"cpu\":6.987502999603748,\"memory\":9.88},{\"round\":0,\"log\":769,\"cpu\":6.515727000311017,\"memory\":13.44},{\"round\":0,\"log\":770,\"cpu\":0.1524090003222227,\"memory\":13.54},{\"round\":0,\"log\":771,\"cpu\":0.1422489993274212,\"memory\":13.64},{\"round\":0,\"log\":772,\"cpu\":0.13184900023043156,\"memory\":13.74},{\"round\":0,\"log\":773,\"cpu\":0.14444000087678432,\"memory\":13.86},{\"round\":0,\"log\":774,\"cpu\":0.12080899998545647,\"memory\":13.96},{\"round\":0,\"log\":775,\"cpu\":113.43668899871409,\"memory\":54.3},{\"round\":0,\"log\":776,\"cpu\":0.06103000044822693,\"memory\":54.3},{\"round\":0,\"log\":777,\"cpu\":42.56839800067246,\"memory\":67.84},{\"round\":0,\"log\":778,\"cpu\":0.060819000005722046,\"memory\":67.84},{\"round\":0,\"log\":779,\"cpu\":6.622266000136733,\"memory\":63.64},{\"round\":0,\"log\":780,\"cpu\":5.611550999805331,\"memory\":69.65},{\"round\":0,\"log\":781,\"cpu\":1.2361730001866817,\"memory\":70.8},{\"round\":0,\"log\":782,\"cpu\":4.3375979997217655,\"memory\":63.44},{\"round\":0,\"log\":783,\"cpu\":0.8333349991589785,\"memory\":64.01},{\"round\":0,\"log\":784,\"cpu\":3.882830999791622,\"memory\":68.09},{\"round\":0,\"log\":785,\"cpu\":0.838425001129508,\"memory\":68.88},{\"round\":0,\"log\":786,\"cpu\":1.8848899994045496,\"memory\":70.92},{\"round\":0,\"log\":787,\"cpu\":5.568880999460816,\"memory\":77.33},{\"round\":0,\"log\":788,\"cpu\":2.5212670005857944,\"memory\":65.75},{\"round\":0,\"log\":789,\"cpu\":2.554237000644207,\"memory\":68.76},{\"round\":0,\"log\":790,\"cpu\":0.5325969997793436,\"memory\":69.34},{\"round\":0,\"log\":791,\"cpu\":3.4481019992381334,\"memory\":73.41},{\"round\":0,\"log\":792,\"cpu\":0.7226960007101297,\"memory\":74.2},{\"round\":0,\"log\":793,\"cpu\":1.896279999986291,\"memory\":76.24},{\"round\":0,\"log\":794,\"cpu\":0.4423779994249344,\"memory\":76.64},{\"round\":0,\"log\":795,\"cpu\":5.320461999624968,\"memory\":67.3},{\"round\":0,\"log\":796,\"cpu\":1.554822001606226,\"memory\":69},{\"round\":0,\"log\":797,\"cpu\":3.7691899985074997,\"memory\":73.19},{\"round\":0,\"log\":798,\"cpu\":0.7887360006570816,\"memory\":73.94},{\"round\":0,\"log\":799,\"cpu\":5.614740999415517,\"memory\":65.75},{\"round\":0,\"log\":800,\"cpu\":1.3057129997760057,\"memory\":66.95},{\"round\":0,\"log\":801,\"cpu\":2.5345670003443956,\"memory\":69.81},{\"round\":0,\"log\":802,\"cpu\":0.5087480004876852,\"memory\":70.34},{\"round\":0,\"log\":803,\"cpu\":5.274482000619173,\"memory\":76.77},{\"round\":0,\"log\":804,\"cpu\":2.716915998607874,\"memory\":65.79},{\"round\":0,\"log\":805,\"cpu\":3.589231001213193,\"memory\":69.99},{\"round\":0,\"log\":806,\"cpu\":0.7972959987819195,\"memory\":70.83},{\"round\":0,\"log\":807,\"cpu\":4.195328000932932,\"memory\":75.49},{\"round\":0,\"log\":808,\"cpu\":1.364112999290228,\"memory\":76.75},{\"round\":0,\"log\":809,\"cpu\":3.7976700011640787,\"memory\":65.92},{\"round\":0,\"log\":810,\"cpu\":0.6030770000070333,\"memory\":66.51},{\"round\":0,\"log\":811,\"cpu\":5.4510919991880655,\"memory\":72.94},{\"round\":0,\"log\":812,\"cpu\":0.09658900089561939,\"memory\":73},{\"round\":0,\"log\":813,\"cpu\":3.7576809991151094,\"memory\":77.13},{\"round\":0,\"log\":814,\"cpu\":0.05550000071525574,\"memory\":77.15},{\"round\":0,\"log\":815,\"cpu\":4.920633999630809,\"memory\":67.55},{\"round\":0,\"log\":816,\"cpu\":0.08532899990677834,\"memory\":67.6},{\"round\":0,\"log\":817,\"cpu\":2.410437999293208,\"memory\":70.41},{\"round\":0,\"log\":818,\"cpu\":0.04642000049352646,\"memory\":70.42},{\"round\":0,\"log\":819,\"cpu\":5.8323490004986525,\"memory\":76.83},{\"round\":0,\"log\":820,\"cpu\":0.14006900042295456,\"memory\":76.92},{\"round\":0,\"log\":821,\"cpu\":4.928194999694824,\"memory\":68.08},{\"round\":0,\"log\":822,\"cpu\":0.08381900005042553,\"memory\":68.13},{\"round\":0,\"log\":823,\"cpu\":3.8562700003385544,\"memory\":72.75},{\"round\":0,\"log\":824,\"cpu\":0.10564999841153622,\"memory\":72.82},{\"round\":0,\"log\":825,\"cpu\":2.5811260007321835,\"memory\":75.61},{\"round\":0,\"log\":826,\"cpu\":0.07472999952733517,\"memory\":75.65},{\"round\":0,\"log\":827,\"cpu\":6.149318000301719,\"memory\":67.94},{\"round\":0,\"log\":828,\"cpu\":0.2035590000450611,\"memory\":68.11},{\"round\":0,\"log\":829,\"cpu\":3.5249809995293617,\"memory\":72.13},{\"round\":0,\"log\":830,\"cpu\":0.1273300014436245,\"memory\":72.22},{\"round\":0,\"log\":831,\"cpu\":4.351506998762488,\"memory\":76.8},{\"round\":0,\"log\":832,\"cpu\":0.16494899988174438,\"memory\":76.92},{\"round\":0,\"log\":833,\"cpu\":3.178913000971079,\"memory\":65.73},{\"round\":0,\"log\":834,\"cpu\":0.10004999861121178,\"memory\":65.8},{\"round\":0,\"log\":835,\"cpu\":5.1927430015057325,\"memory\":72.16},{\"round\":0,\"log\":836,\"cpu\":0.34079799987375736,\"memory\":72.49},{\"round\":0,\"log\":837,\"cpu\":3.4204120002686977,\"memory\":76.36},{\"round\":0,\"log\":838,\"cpu\":0.17870899848639965,\"memory\":76.52},{\"round\":0,\"log\":839,\"cpu\":5.64402100071311,\"memory\":66.68},{\"round\":0,\"log\":840,\"cpu\":0.28222900070250034,\"memory\":66.91},{\"round\":0,\"log\":841,\"cpu\":2.2716579996049404,\"memory\":69.54},{\"round\":0,\"log\":842,\"cpu\":0.1497489996254444,\"memory\":69.66},{\"round\":0,\"log\":843,\"cpu\":5.238262999802828,\"memory\":75.98},{\"round\":0,\"log\":844,\"cpu\":0.06376899965107441,\"memory\":76},{\"round\":0,\"log\":845,\"cpu\":4.980805000290275,\"memory\":67.55},{\"round\":0,\"log\":846,\"cpu\":0.040859000757336617,\"memory\":67.56},{\"round\":0,\"log\":847,\"cpu\":3.8907500002533197,\"memory\":72.21},{\"round\":0,\"log\":848,\"cpu\":0.04814999923110008,\"memory\":72.24},{\"round\":0,\"log\":849,\"cpu\":2.4970769993960857,\"memory\":75.08},{\"round\":0,\"log\":850,\"cpu\":0.035809000954031944,\"memory\":75.09},{\"round\":0,\"log\":851,\"cpu\":6.265138000249863,\"memory\":67.7},{\"round\":0,\"log\":852,\"cpu\":0.06109900027513504,\"memory\":67.73},{\"round\":0,\"log\":853,\"cpu\":3.703890999779105,\"memory\":71.89},{\"round\":0,\"log\":854,\"cpu\":0.04394000023603439,\"memory\":71.91},{\"round\":0,\"log\":855,\"cpu\":4.477866999804974,\"memory\":76.56},{\"round\":0,\"log\":856,\"cpu\":0.05858999863266945,\"memory\":76.59},{\"round\":0,\"log\":857,\"cpu\":3.2164330016821623,\"memory\":65.74},{\"round\":0,\"log\":858,\"cpu\":0.044040000066161156,\"memory\":65.76},{\"round\":0,\"log\":859,\"cpu\":5.235461998730898,\"memory\":72.17},{\"round\":0,\"log\":860,\"cpu\":0.0711400005966425,\"memory\":72.22},{\"round\":0,\"log\":861,\"cpu\":3.7018710002303123,\"memory\":76.38},{\"round\":0,\"log\":862,\"cpu\":0.05038899928331375,\"memory\":76.4},{\"round\":0,\"log\":863,\"cpu\":4.993644000962377,\"memory\":67.07},{\"round\":0,\"log\":864,\"cpu\":0.07329999841749668,\"memory\":67.11},{\"round\":0,\"log\":865,\"cpu\":2.418547000735998,\"memory\":69.94},{\"round\":0,\"log\":866,\"cpu\":0.04763999953866005,\"memory\":69.97},{\"round\":0,\"log\":867,\"cpu\":5.577021000906825,\"memory\":76.38},{\"round\":0,\"log\":868,\"cpu\":0.1420889999717474,\"memory\":76.46},{\"round\":0,\"log\":869,\"cpu\":4.973133999854326,\"memory\":67.88},{\"round\":0,\"log\":870,\"cpu\":0.06849000044167042,\"memory\":67.91},{\"round\":0,\"log\":871,\"cpu\":3.910209998488426,\"memory\":72.57},{\"round\":0,\"log\":872,\"cpu\":0.09667900018393993,\"memory\":72.64},{\"round\":0,\"log\":873,\"cpu\":2.744065999984741,\"memory\":75.47},{\"round\":0,\"log\":874,\"cpu\":0.0670900009572506,\"memory\":75.5},{\"round\":0,\"log\":875,\"cpu\":5.707590000703931,\"memory\":64.4},{\"round\":0,\"log\":876,\"cpu\":0.2116289995610714,\"memory\":64.48},{\"round\":0,\"log\":877,\"cpu\":0.15844899974763393,\"memory\":64.55},{\"round\":0,\"log\":878,\"cpu\":0.2607579994946718,\"memory\":64.69},{\"round\":0,\"log\":879,\"cpu\":0.2486790008842945,\"memory\":64.83},{\"round\":0,\"log\":880,\"cpu\":0.45745799876749516,\"memory\":65.09},{\"round\":0,\"log\":881,\"cpu\":0.4538580011576414,\"memory\":65.35},{\"round\":0,\"log\":882,\"cpu\":0.9124849997460842,\"memory\":65.87},{\"round\":0,\"log\":883,\"cpu\":0.19127899967134,\"memory\":65.99},{\"round\":0,\"log\":884,\"cpu\":4.809894999489188,\"memory\":71.09},{\"round\":0,\"log\":885,\"cpu\":2.000569000840187,\"memory\":72.84},{\"round\":0,\"log\":886,\"cpu\":5.809949999675155,\"memory\":65.44},{\"round\":0,\"log\":887,\"cpu\":1.006164999678731,\"memory\":66.45},{\"round\":0,\"log\":888,\"cpu\":3.8358500003814697,\"memory\":71.28},{\"round\":0,\"log\":889,\"cpu\":0.7102659996598959,\"memory\":72.18},{\"round\":0,\"log\":890,\"cpu\":4.00190900079906,\"memory\":76.97},{\"round\":0,\"log\":891,\"cpu\":0.7991059999912977,\"memory\":77.86},{\"round\":0,\"log\":892,\"cpu\":17.390899999067187,\"memory\":72.51},{\"round\":0,\"log\":893,\"cpu\":10.635053999722004,\"memory\":73.8},{\"round\":0,\"log\":894,\"cpu\":2.0035190004855394,\"memory\":75.55},{\"round\":0,\"log\":895,\"cpu\":4.583527000620961,\"memory\":80.69},{\"round\":0,\"log\":896,\"cpu\":0.9239649996161461,\"memory\":81.71},{\"round\":0,\"log\":897,\"cpu\":5.318072000518441,\"memory\":73.05},{\"round\":0,\"log\":898,\"cpu\":0.9445949997752905,\"memory\":73.95},{\"round\":0,\"log\":899,\"cpu\":4.285497998818755,\"memory\":78.74},{\"round\":0,\"log\":900,\"cpu\":0.7265560012310743,\"memory\":79.63},{\"round\":0,\"log\":901,\"cpu\":16.08156600035727,\"memory\":84.9},{\"round\":0,\"log\":902,\"cpu\":5.7389399986714125,\"memory\":80.36},{\"round\":0,\"log\":903,\"cpu\":4.908595001325011,\"memory\":85.46},{\"round\":0,\"log\":904,\"cpu\":6.317946998402476,\"memory\":89},{\"round\":0,\"log\":905,\"cpu\":9.260912001132965,\"memory\":86.93},{\"round\":0,\"log\":906,\"cpu\":1.7183609995990992,\"memory\":88.73},{\"round\":0,\"log\":907,\"cpu\":6.509026000276208,\"memory\":83.42},{\"round\":0,\"log\":908,\"cpu\":1.0383850000798702,\"memory\":84.86},{\"round\":0,\"log\":909,\"cpu\":5.1867319997400045,\"memory\":90.55},{\"round\":0,\"log\":910,\"cpu\":0.8267759997397661,\"memory\":91.8},{\"round\":0,\"log\":911,\"cpu\":6.566166000440717,\"memory\":85.03},{\"round\":0,\"log\":912,\"cpu\":0.1119800005108118,\"memory\":85.11},{\"round\":0,\"log\":913,\"cpu\":6.332915998995304,\"memory\":92.02},{\"round\":0,\"log\":914,\"cpu\":0.05444999970495701,\"memory\":92.04},{\"round\":0,\"log\":915,\"cpu\":6.119148001074791,\"memory\":85.13},{\"round\":0,\"log\":916,\"cpu\":0.05001999996602535,\"memory\":85.15},{\"round\":0,\"log\":917,\"cpu\":4.990173999220133,\"memory\":90.84},{\"round\":0,\"log\":918,\"cpu\":0.04430000111460686,\"memory\":90.85},{\"round\":0,\"log\":919,\"cpu\":6.424425998702645,\"memory\":84.49},{\"round\":0,\"log\":920,\"cpu\":0.0979399997740984,\"memory\":84.58},{\"round\":0,\"log\":921,\"cpu\":6.396186999976635,\"memory\":91.48},{\"round\":0,\"log\":922,\"cpu\":0.05233000032603741,\"memory\":91.5},{\"round\":0,\"log\":923,\"cpu\":6.358996000140905,\"memory\":84.88},{\"round\":0,\"log\":924,\"cpu\":0.049390001222491264,\"memory\":84.89},{\"round\":0,\"log\":925,\"cpu\":4.9640339985489845,\"memory\":90.59},{\"round\":0,\"log\":926,\"cpu\":0.04447000101208687,\"memory\":90.6},{\"round\":0,\"log\":927,\"cpu\":6.672824999317527,\"memory\":84.37},{\"round\":0,\"log\":928,\"cpu\":0.09771000035107136,\"memory\":84.45},{\"round\":0,\"log\":929,\"cpu\":6.391776999458671,\"memory\":91.34},{\"round\":0,\"log\":930,\"cpu\":0.06142900139093399,\"memory\":91.38},{\"round\":0,\"log\":931,\"cpu\":5.789349999278784,\"memory\":84.74},{\"round\":0,\"log\":932,\"cpu\":0.11264899931848049,\"memory\":84.83},{\"round\":0,\"log\":933,\"cpu\":4.8922850005328655,\"memory\":90.43},{\"round\":0,\"log\":934,\"cpu\":0.1809889990836382,\"memory\":90.61},{\"round\":0,\"log\":935,\"cpu\":6.193938000127673,\"memory\":83.8},{\"round\":0,\"log\":936,\"cpu\":0.1108190007507801,\"memory\":83.88},{\"round\":0,\"log\":937,\"cpu\":6.358816999942064,\"memory\":90.77},{\"round\":0,\"log\":938,\"cpu\":0.06454999931156635,\"memory\":90.8},{\"round\":0,\"log\":939,\"cpu\":5.762000000104308,\"memory\":84.4},{\"round\":0,\"log\":940,\"cpu\":0.1098990011960268,\"memory\":84.49},{\"round\":0,\"log\":941,\"cpu\":4.788944998756051,\"memory\":90.09},{\"round\":0,\"log\":942,\"cpu\":0.20282900147140026,\"memory\":90.27},{\"round\":0,\"log\":943,\"cpu\":6.731464998796582,\"memory\":83.59},{\"round\":0,\"log\":944,\"cpu\":0.14423900097608566,\"memory\":83.68},{\"round\":0,\"log\":945,\"cpu\":6.335456999018788,\"memory\":90.58},{\"round\":0,\"log\":946,\"cpu\":0.08338000066578388,\"memory\":90.63},{\"round\":0,\"log\":947,\"cpu\":5.8273399993777275,\"memory\":84.37},{\"round\":0,\"log\":948,\"cpu\":0.15005899965763092,\"memory\":84.54},{\"round\":0,\"log\":949,\"cpu\":4.7691950015723705,\"memory\":90.23},{\"round\":0,\"log\":950,\"cpu\":0.2573289982974529,\"memory\":90.55},{\"round\":0,\"log\":951,\"cpu\":6.67157500050962,\"memory\":84.33},{\"round\":0,\"log\":952,\"cpu\":0.1172690000385046,\"memory\":84.43},{\"round\":0,\"log\":953,\"cpu\":6.395247001200914,\"memory\":91.33},{\"round\":0,\"log\":954,\"cpu\":0.07710999995470047,\"memory\":91.39},{\"round\":0,\"log\":955,\"cpu\":5.777308998629451,\"memory\":84.78},{\"round\":0,\"log\":956,\"cpu\":0.15005000121891499,\"memory\":84.95},{\"round\":0,\"log\":957,\"cpu\":4.876774000003934,\"memory\":90.64},{\"round\":0,\"log\":958,\"cpu\":0.2443690001964569,\"memory\":90.95},{\"round\":0,\"log\":959,\"cpu\":6.559285998344421,\"memory\":84.52},{\"round\":0,\"log\":960,\"cpu\":6.452576000243425,\"memory\":88.06},{\"round\":0,\"log\":961,\"cpu\":6.483307000249624,\"memory\":91.62},{\"round\":0,\"log\":962,\"cpu\":0.15351900085806847,\"memory\":91.72},{\"round\":0,\"log\":963,\"cpu\":0.15314899943768978,\"memory\":91.83},{\"round\":0,\"log\":964,\"cpu\":0.13731000013649464,\"memory\":91.92},{\"round\":0,\"log\":965,\"cpu\":0.14920900017023087,\"memory\":92.04},{\"round\":0,\"log\":966,\"cpu\":0.12447899952530861,\"memory\":92.14},{\"round\":0,\"log\":967,\"cpu\":122.85288999974728,\"memory\":54.51},{\"round\":0,\"log\":968,\"cpu\":0.08747000060975552,\"memory\":54.51},{\"round\":0,\"log\":969,\"cpu\":45.8900709990412,\"memory\":61.3},{\"round\":0,\"log\":970,\"cpu\":0.06063000112771988,\"memory\":61.3}],[{\"round\":1,\"log\":0,\"cpu\":18.0321359988302,\"memory\":10.37},{\"round\":1,\"log\":1,\"cpu\":2.217009000480175,\"memory\":11.62},{\"round\":1,\"log\":2,\"cpu\":0.5830370001494884,\"memory\":11.63},{\"round\":1,\"log\":3,\"cpu\":0.3182479999959469,\"memory\":11.66},{\"round\":1,\"log\":4,\"cpu\":0.12048899941146374,\"memory\":11.67},{\"round\":1,\"log\":5,\"cpu\":0.11402999982237816,\"memory\":11.69},{\"round\":1,\"log\":6,\"cpu\":0.06164900027215481,\"memory\":11.7},{\"round\":1,\"log\":7,\"cpu\":0.455248000100255,\"memory\":11.83},{\"round\":1,\"log\":8,\"cpu\":0.12059899978339672,\"memory\":11.85},{\"round\":1,\"log\":9,\"cpu\":0.20502900145947933,\"memory\":11.91},{\"round\":1,\"log\":10,\"cpu\":0.1076899990439415,\"memory\":11.93},{\"round\":1,\"log\":11,\"cpu\":1.85152000002563,\"memory\":13.53},{\"round\":1,\"log\":12,\"cpu\":11.167462000623345,\"memory\":7.01},{\"round\":1,\"log\":13,\"cpu\":1.3866530004888773,\"memory\":8.13},{\"round\":1,\"log\":14,\"cpu\":3.8942889999598265,\"memory\":11.27},{\"round\":1,\"log\":15,\"cpu\":0.7020560000091791,\"memory\":11.84},{\"round\":1,\"log\":16,\"cpu\":5.202873999252915,\"memory\":16.07},{\"round\":1,\"log\":17,\"cpu\":2.6959860008209944,\"memory\":4.48},{\"round\":1,\"log\":18,\"cpu\":2.613805999979377,\"memory\":6.57},{\"round\":1,\"log\":19,\"cpu\":7.405650999397039,\"memory\":13.15},{\"round\":1,\"log\":20,\"cpu\":1.4899530000984669,\"memory\":14.28},{\"round\":1,\"log\":21,\"cpu\":3.5131320003420115,\"memory\":17.36},{\"round\":1,\"log\":22,\"cpu\":1.4589719995856285,\"memory\":3.75},{\"round\":1,\"log\":23,\"cpu\":4.486945999786258,\"memory\":7.92},{\"round\":1,\"log\":24,\"cpu\":0.9622159991413355,\"memory\":8.7},{\"round\":1,\"log\":25,\"cpu\":2.249328000470996,\"memory\":10.78},{\"round\":1,\"log\":26,\"cpu\":0.49856700003147125,\"memory\":11.17},{\"round\":1,\"log\":27,\"cpu\":6.067799000069499,\"memory\":17.31},{\"round\":1,\"log\":28,\"cpu\":3.002563999965787,\"memory\":6.32},{\"round\":1,\"log\":29,\"cpu\":4.388346999883652,\"memory\":10.58},{\"round\":1,\"log\":30,\"cpu\":0.856156000867486,\"memory\":11.34},{\"round\":1,\"log\":31,\"cpu\":5.1017029993236065,\"memory\":16.14},{\"round\":1,\"log\":32,\"cpu\":1.6700010001659393,\"memory\":17.35},{\"round\":1,\"log\":33,\"cpu\":3.8934499993920326,\"memory\":6.53},{\"round\":1,\"log\":34,\"cpu\":0.6608969997614622,\"memory\":7.08},{\"round\":1,\"log\":35,\"cpu\":6.997573001310229,\"memory\":13.96},{\"round\":1,\"log\":36,\"cpu\":2.1462689992040396,\"memory\":15.73},{\"round\":1,\"log\":37,\"cpu\":5.586481001228094,\"memory\":7.75},{\"round\":1,\"log\":38,\"cpu\":0.8915749993175268,\"memory\":8.58},{\"round\":1,\"log\":39,\"cpu\":4.537846999242902,\"memory\":13.27},{\"round\":1,\"log\":40,\"cpu\":1.5059220008552074,\"memory\":14.53},{\"round\":1,\"log\":41,\"cpu\":2.9370949994772673,\"memory\":17.39},{\"round\":1,\"log\":42,\"cpu\":0.7041859999299049,\"memory\":17.99},{\"round\":1,\"log\":43,\"cpu\":6.615856001153588,\"memory\":9.8},{\"round\":1,\"log\":44,\"cpu\":0.14555899985134602,\"memory\":9.86},{\"round\":1,\"log\":45,\"cpu\":4.235756998881698,\"memory\":13.98},{\"round\":1,\"log\":46,\"cpu\":0.0645700003951788,\"memory\":14},{\"round\":1,\"log\":47,\"cpu\":5.434242000803351,\"memory\":6.09},{\"round\":1,\"log\":48,\"cpu\":0.12049999833106995,\"memory\":6.14},{\"round\":1,\"log\":49,\"cpu\":2.7250050008296967,\"memory\":8.95},{\"round\":1,\"log\":50,\"cpu\":0.05258000083267689,\"memory\":8.97},{\"round\":1,\"log\":51,\"cpu\":5.680139999836683,\"memory\":15.4},{\"round\":1,\"log\":52,\"cpu\":0.15860899910330772,\"memory\":15.5},{\"round\":1,\"log\":53,\"cpu\":5.111263999715447,\"memory\":7.4},{\"round\":1,\"log\":54,\"cpu\":0.09985900111496449,\"memory\":7.45},{\"round\":1,\"log\":55,\"cpu\":4.473817000165582,\"memory\":12.09},{\"round\":1,\"log\":56,\"cpu\":0.1331389993429184,\"memory\":12.16},{\"round\":1,\"log\":57,\"cpu\":2.7918359991163015,\"memory\":14.95},{\"round\":1,\"log\":58,\"cpu\":0.08253900147974491,\"memory\":14.99},{\"round\":1,\"log\":59,\"cpu\":6.672335999086499,\"memory\":7.98},{\"round\":1,\"log\":60,\"cpu\":0.24553800001740456,\"memory\":8.15},{\"round\":1,\"log\":61,\"cpu\":4.044309999793768,\"memory\":12.17},{\"round\":1,\"log\":62,\"cpu\":0.13123900070786476,\"memory\":12.26},{\"round\":1,\"log\":63,\"cpu\":4.547445999458432,\"memory\":16.86},{\"round\":1,\"log\":64,\"cpu\":0.18688900023698807,\"memory\":16.98},{\"round\":1,\"log\":65,\"cpu\":3.5267719998955727,\"memory\":5.97},{\"round\":1,\"log\":66,\"cpu\":0.11476900056004524,\"memory\":6.04},{\"round\":1,\"log\":67,\"cpu\":5.531640999019146,\"memory\":12.43},{\"round\":1,\"log\":68,\"cpu\":0.37777800112962723,\"memory\":12.75},{\"round\":1,\"log\":69,\"cpu\":3.7154009994119406,\"memory\":16.62},{\"round\":1,\"log\":70,\"cpu\":0.20436899922788143,\"memory\":16.78},{\"round\":1,\"log\":71,\"cpu\":4.89355400018394,\"memory\":7.18},{\"round\":1,\"log\":72,\"cpu\":0.3183890003710985,\"memory\":7.41},{\"round\":1,\"log\":73,\"cpu\":2.4378169998526573,\"memory\":10.05},{\"round\":1,\"log\":74,\"cpu\":0.15751999989151955,\"memory\":10.16},{\"round\":1,\"log\":75,\"cpu\":5.868869001045823,\"memory\":16.51},{\"round\":1,\"log\":76,\"cpu\":0.08026899956166744,\"memory\":16.54},{\"round\":1,\"log\":77,\"cpu\":4.790784999728203,\"memory\":8.19},{\"round\":1,\"log\":78,\"cpu\":0.0456399992108345,\"memory\":8.2},{\"round\":1,\"log\":79,\"cpu\":4.149259001016617,\"memory\":12.87},{\"round\":1,\"log\":80,\"cpu\":0.05984899960458279,\"memory\":12.9},{\"round\":1,\"log\":81,\"cpu\":2.842245999723673,\"memory\":15.73},{\"round\":1,\"log\":82,\"cpu\":0.03959000110626221,\"memory\":15.74},{\"round\":1,\"log\":83,\"cpu\":6.419395999982953,\"memory\":8.45},{\"round\":1,\"log\":84,\"cpu\":0.07117000035941601,\"memory\":8.49},{\"round\":1,\"log\":85,\"cpu\":3.9180989991873503,\"memory\":12.64},{\"round\":1,\"log\":86,\"cpu\":0.05048000067472458,\"memory\":12.65},{\"round\":1,\"log\":87,\"cpu\":4.717424999922514,\"memory\":17.34},{\"round\":1,\"log\":88,\"cpu\":0.06537999957799911,\"memory\":17.37},{\"round\":1,\"log\":89,\"cpu\":3.449082000181079,\"memory\":6.5},{\"round\":1,\"log\":90,\"cpu\":0.04968000017106533,\"memory\":6.52},{\"round\":1,\"log\":91,\"cpu\":5.45045099966228,\"memory\":12.95},{\"round\":1,\"log\":92,\"cpu\":0.08252999931573868,\"memory\":13},{\"round\":1,\"log\":93,\"cpu\":3.99413900077343,\"memory\":17.14},{\"round\":1,\"log\":94,\"cpu\":0.06592999957501888,\"memory\":17.17},{\"round\":1,\"log\":95,\"cpu\":5.920678999274969,\"memory\":7.81},{\"round\":1,\"log\":96,\"cpu\":0.08580000139772892,\"memory\":7.85},{\"round\":1,\"log\":97,\"cpu\":2.563425999134779,\"memory\":10.68},{\"round\":1,\"log\":98,\"cpu\":0.05200999975204468,\"memory\":10.7},{\"round\":1,\"log\":99,\"cpu\":5.942329000681639,\"memory\":17.13},{\"round\":1,\"log\":100,\"cpu\":0.12917899899184704,\"memory\":17.21},{\"round\":1,\"log\":101,\"cpu\":4.616016000509262,\"memory\":8.64},{\"round\":1,\"log\":102,\"cpu\":0.0801400002092123,\"memory\":8.68},{\"round\":1,\"log\":103,\"cpu\":4.104769000783563,\"memory\":13.34},{\"round\":1,\"log\":104,\"cpu\":0.1369089987128973,\"memory\":13.41},{\"round\":1,\"log\":105,\"cpu\":2.9719540011137724,\"memory\":16.23},{\"round\":1,\"log\":106,\"cpu\":0.0904999990016222,\"memory\":16.27},{\"round\":1,\"log\":107,\"cpu\":5.826359000056982,\"memory\":4.99},{\"round\":1,\"log\":108,\"cpu\":0.21237900108098984,\"memory\":5.07},{\"round\":1,\"log\":109,\"cpu\":0.161379000172019,\"memory\":5.15},{\"round\":1,\"log\":110,\"cpu\":0.26572899892926216,\"memory\":5.29},{\"round\":1,\"log\":111,\"cpu\":0.25222899951040745,\"memory\":5.42},{\"round\":1,\"log\":112,\"cpu\":0.5577770005911589,\"memory\":5.68},{\"round\":1,\"log\":113,\"cpu\":0.43761800043284893,\"memory\":5.94},{\"round\":1,\"log\":114,\"cpu\":0.8710249997675419,\"memory\":6.46},{\"round\":1,\"log\":115,\"cpu\":0.20758900046348572,\"memory\":6.58},{\"round\":1,\"log\":116,\"cpu\":5.1242829989641905,\"memory\":11.75},{\"round\":1,\"log\":117,\"cpu\":2.020840000361204,\"memory\":13.47},{\"round\":1,\"log\":118,\"cpu\":5.913538999855518,\"memory\":6.17},{\"round\":1,\"log\":119,\"cpu\":1.0260039996355772,\"memory\":7.16},{\"round\":1,\"log\":120,\"cpu\":4.24464900046587,\"memory\":12.06},{\"round\":1,\"log\":121,\"cpu\":0.7575160004198551,\"memory\":12.93},{\"round\":1,\"log\":122,\"cpu\":4.4795559998601675,\"memory\":17.79},{\"round\":1,\"log\":123,\"cpu\":0.8024659994989634,\"memory\":18.65},{\"round\":1,\"log\":124,\"cpu\":18.649263000115752,\"memory\":13.42},{\"round\":1,\"log\":125,\"cpu\":11.317831000313163,\"memory\":14.66},{\"round\":1,\"log\":126,\"cpu\":2.131649000570178,\"memory\":16.38},{\"round\":1,\"log\":127,\"cpu\":4.768884999677539,\"memory\":21.54},{\"round\":1,\"log\":128,\"cpu\":1.048905000090599,\"memory\":22.52},{\"round\":1,\"log\":129,\"cpu\":5.136802999302745,\"memory\":13.99},{\"round\":1,\"log\":130,\"cpu\":0.9840550012886524,\"memory\":14.86},{\"round\":1,\"log\":131,\"cpu\":4.385816998779774,\"memory\":19.66},{\"round\":1,\"log\":132,\"cpu\":0.8209659997373819,\"memory\":20.52},{\"round\":1,\"log\":133,\"cpu\":17.56016799993813,\"memory\":25.78},{\"round\":1,\"log\":134,\"cpu\":5.6610010005533695,\"memory\":21.14},{\"round\":1,\"log\":135,\"cpu\":5.249373000115156,\"memory\":26.25},{\"round\":1,\"log\":136,\"cpu\":7.039042999967933,\"memory\":29.89},{\"round\":1,\"log\":137,\"cpu\":9.575139999389648,\"memory\":27.94},{\"round\":1,\"log\":138,\"cpu\":1.7370210010558367,\"memory\":29.72},{\"round\":1,\"log\":139,\"cpu\":6.738064998760819,\"memory\":24.3},{\"round\":1,\"log\":140,\"cpu\":1.123234000056982,\"memory\":25.71},{\"round\":1,\"log\":141,\"cpu\":5.50378100015223,\"memory\":31.39},{\"round\":1,\"log\":142,\"cpu\":0.8907160013914108,\"memory\":32.62},{\"round\":1,\"log\":143,\"cpu\":6.899483999237418,\"memory\":25.81},{\"round\":1,\"log\":144,\"cpu\":0.1222389992326498,\"memory\":25.89},{\"round\":1,\"log\":145,\"cpu\":6.685615001246333,\"memory\":32.78},{\"round\":1,\"log\":146,\"cpu\":0.05814000032842159,\"memory\":32.8},{\"round\":1,\"log\":147,\"cpu\":6.341066999360919,\"memory\":25.92},{\"round\":1,\"log\":148,\"cpu\":0.05013999901711941,\"memory\":25.93},{\"round\":1,\"log\":149,\"cpu\":5.085853001102805,\"memory\":31.61},{\"round\":1,\"log\":150,\"cpu\":0.04818999953567982,\"memory\":31.62},{\"round\":1,\"log\":151,\"cpu\":6.610816000029445,\"memory\":25.28},{\"round\":1,\"log\":152,\"cpu\":0.1040790006518364,\"memory\":25.36},{\"round\":1,\"log\":153,\"cpu\":6.809034999459982,\"memory\":32.25},{\"round\":1,\"log\":154,\"cpu\":0.05261999927461147,\"memory\":32.27},{\"round\":1,\"log\":155,\"cpu\":6.0484580006450415,\"memory\":25.64},{\"round\":1,\"log\":156,\"cpu\":0.05064000003039837,\"memory\":25.65},{\"round\":1,\"log\":157,\"cpu\":5.155372999608517,\"memory\":31.33},{\"round\":1,\"log\":158,\"cpu\":0.046509999781847,\"memory\":31.34},{\"round\":1,\"log\":159,\"cpu\":7.247572001069784,\"memory\":25.12},{\"round\":1,\"log\":160,\"cpu\":0.09978899918496609,\"memory\":25.2},{\"round\":1,\"log\":161,\"cpu\":6.775815000757575,\"memory\":32.08},{\"round\":1,\"log\":162,\"cpu\":0.06481000036001205,\"memory\":32.11},{\"round\":1,\"log\":163,\"cpu\":6.282596999779344,\"memory\":25.45},{\"round\":1,\"log\":164,\"cpu\":0.11911999993026257,\"memory\":25.54},{\"round\":1,\"log\":165,\"cpu\":5.0647630002349615,\"memory\":31.13},{\"round\":1,\"log\":166,\"cpu\":0.18300899863243103,\"memory\":31.31},{\"round\":1,\"log\":167,\"cpu\":6.474186001345515,\"memory\":24.53},{\"round\":1,\"log\":168,\"cpu\":0.11620000004768372,\"memory\":24.61},{\"round\":1,\"log\":169,\"cpu\":6.574015999212861,\"memory\":31.49},{\"round\":1,\"log\":170,\"cpu\":0.06753900088369846,\"memory\":31.52},{\"round\":1,\"log\":171,\"cpu\":6.067928999662399,\"memory\":25.19},{\"round\":1,\"log\":172,\"cpu\":0.11513900011777878,\"memory\":25.28},{\"round\":1,\"log\":173,\"cpu\":4.788954999297857,\"memory\":30.87},{\"round\":1,\"log\":174,\"cpu\":0.18886899948120117,\"memory\":31.05},{\"round\":1,\"log\":175,\"cpu\":6.803365001454949,\"memory\":24.4},{\"round\":1,\"log\":176,\"cpu\":0.20917899906635284,\"memory\":24.53},{\"round\":1,\"log\":177,\"cpu\":6.7277049999684095,\"memory\":31.41},{\"round\":1,\"log\":178,\"cpu\":0.09494899958372116,\"memory\":31.46},{\"round\":1,\"log\":179,\"cpu\":5.904859000816941,\"memory\":25.2},{\"round\":1,\"log\":180,\"cpu\":0.1531699988991022,\"memory\":25.36},{\"round\":1,\"log\":181,\"cpu\":5.084283001720905,\"memory\":31.04},{\"round\":1,\"log\":182,\"cpu\":0.2725189998745918,\"memory\":31.35},{\"round\":1,\"log\":183,\"cpu\":6.818283999338746,\"memory\":25.14},{\"round\":1,\"log\":184,\"cpu\":0.19342900067567825,\"memory\":25.27},{\"round\":1,\"log\":185,\"cpu\":6.6124959997832775,\"memory\":32.15},{\"round\":1,\"log\":186,\"cpu\":0.08471900038421154,\"memory\":32.2},{\"round\":1,\"log\":187,\"cpu\":5.9486289992928505,\"memory\":25.58},{\"round\":1,\"log\":188,\"cpu\":0.16850999929010868,\"memory\":25.74},{\"round\":1,\"log\":189,\"cpu\":5.080953000113368,\"memory\":31.41},{\"round\":1,\"log\":190,\"cpu\":0.2596589997410774,\"memory\":31.72},{\"round\":1,\"log\":191,\"cpu\":6.713504999876022,\"memory\":25.36},{\"round\":1,\"log\":192,\"cpu\":7.301592001691461,\"memory\":28.99},{\"round\":1,\"log\":193,\"cpu\":6.990142999216914,\"memory\":32.61},{\"round\":1,\"log\":194,\"cpu\":0.24665899947285652,\"memory\":32.74},{\"round\":1,\"log\":195,\"cpu\":0.22854899987578392,\"memory\":32.88},{\"round\":1,\"log\":196,\"cpu\":0.21734900027513504,\"memory\":33.03},{\"round\":1,\"log\":197,\"cpu\":0.22774899937212467,\"memory\":33.17},{\"round\":1,\"log\":198,\"cpu\":0.21172800101339817,\"memory\":33.31},{\"round\":1,\"log\":199,\"cpu\":121.65973700024188,\"memory\":69.99},{\"round\":1,\"log\":200,\"cpu\":0.06495999917387962,\"memory\":69.99},{\"round\":1,\"log\":201,\"cpu\":47.79794100113213,\"memory\":76.23},{\"round\":1,\"log\":202,\"cpu\":0.060669999569654465,\"memory\":76.23},{\"round\":1,\"log\":203,\"cpu\":3.7754100002348423,\"memory\":79.02},{\"round\":1,\"log\":204,\"cpu\":8.017078999429941,\"memory\":78.42},{\"round\":1,\"log\":205,\"cpu\":1.35916299931705,\"memory\":79.54},{\"round\":1,\"log\":206,\"cpu\":2.785395000129938,\"memory\":82.56},{\"round\":1,\"log\":207,\"cpu\":0.6127070002257824,\"memory\":83.12},{\"round\":1,\"log\":208,\"cpu\":3.964979000389576,\"memory\":87.21},{\"round\":1,\"log\":209,\"cpu\":0.8670060001313686,\"memory\":87.99},{\"round\":1,\"log\":210,\"cpu\":2.5824859999120235,\"memory\":75.4},{\"round\":1,\"log\":211,\"cpu\":6.160948000848293,\"memory\":81.83},{\"round\":1,\"log\":212,\"cpu\":1.318962998688221,\"memory\":82.95},{\"round\":1,\"log\":213,\"cpu\":2.621256999671459,\"memory\":85.97},{\"round\":1,\"log\":214,\"cpu\":0.6222760006785393,\"memory\":86.53},{\"round\":1,\"log\":215,\"cpu\":4.5905269999057055,\"memory\":76.22},{\"round\":1,\"log\":216,\"cpu\":0.9489850010722876,\"memory\":76.99},{\"round\":1,\"log\":217,\"cpu\":1.7815600000321865,\"memory\":79.04},{\"round\":1,\"log\":218,\"cpu\":0.4111579991877079,\"memory\":79.43},{\"round\":1,\"log\":219,\"cpu\":5.049963999539614,\"memory\":85.46},{\"round\":1,\"log\":220,\"cpu\":1.6553610004484653,\"memory\":87.13},{\"round\":1,\"log\":221,\"cpu\":4.643225999549031,\"memory\":78.99},{\"round\":1,\"log\":222,\"cpu\":0.7238769996911287,\"memory\":79.74},{\"round\":1,\"log\":223,\"cpu\":4.126258000731468,\"memory\":84.41},{\"round\":1,\"log\":224,\"cpu\":1.2840330004692078,\"memory\":85.59},{\"round\":1,\"log\":225,\"cpu\":2.8560750000178814,\"memory\":88.44},{\"round\":1,\"log\":226,\"cpu\":0.645736999809742,\"memory\":88.98},{\"round\":1,\"log\":227,\"cpu\":6.242926999926567,\"memory\":80.74},{\"round\":1,\"log\":228,\"cpu\":1.8718309998512268,\"memory\":82.49},{\"round\":1,\"log\":229,\"cpu\":3.947199000045657,\"memory\":86.66},{\"round\":1,\"log\":230,\"cpu\":0.7662559989839792,\"memory\":87.49},{\"round\":1,\"log\":231,\"cpu\":5.270013000816107,\"memory\":78.5},{\"round\":1,\"log\":232,\"cpu\":1.329483000561595,\"memory\":79.74},{\"round\":1,\"log\":233,\"cpu\":2.5740859992802143,\"memory\":82.59},{\"round\":1,\"log\":234,\"cpu\":0.5945769995450974,\"memory\":83.18},{\"round\":1,\"log\":235,\"cpu\":6.9125540014356375,\"memory\":77.65},{\"round\":1,\"log\":236,\"cpu\":0.1147099994122982,\"memory\":77.71},{\"round\":1,\"log\":237,\"cpu\":3.7152810003608465,\"memory\":81.82},{\"round\":1,\"log\":238,\"cpu\":0.05362899973988533,\"memory\":81.84},{\"round\":1,\"log\":239,\"cpu\":4.3183979988098145,\"memory\":86.49},{\"round\":1,\"log\":240,\"cpu\":0.08860900066792965,\"memory\":86.54},{\"round\":1,\"log\":241,\"cpu\":3.5888219997286797,\"memory\":76.49},{\"round\":1,\"log\":242,\"cpu\":0.05335900001227856,\"memory\":76.51},{\"round\":1,\"log\":243,\"cpu\":5.609301000833511,\"memory\":82.93},{\"round\":1,\"log\":244,\"cpu\":0.13185999915003777,\"memory\":83.02},{\"round\":1,\"log\":245,\"cpu\":3.7938400004059076,\"memory\":87.1},{\"round\":1,\"log\":246,\"cpu\":0.08966900035738945,\"memory\":87.15},{\"round\":1,\"log\":247,\"cpu\":5.098563998937607,\"memory\":78.19},{\"round\":1,\"log\":248,\"cpu\":0.12183899991214275,\"memory\":78.27},{\"round\":1,\"log\":249,\"cpu\":2.501297000795603,\"memory\":81.05},{\"round\":1,\"log\":250,\"cpu\":0.07393000088632107,\"memory\":81.09},{\"round\":1,\"log\":251,\"cpu\":5.608200998976827,\"memory\":87.5},{\"round\":1,\"log\":252,\"cpu\":0.20087799988687038,\"memory\":87.66},{\"round\":1,\"log\":253,\"cpu\":5.054494000971317,\"memory\":78.85},{\"round\":1,\"log\":254,\"cpu\":0.12913999892771244,\"memory\":78.94},{\"round\":1,\"log\":255,\"cpu\":4.459885999560356,\"memory\":83.52},{\"round\":1,\"log\":256,\"cpu\":0.18517900072038174,\"memory\":83.65},{\"round\":1,\"log\":257,\"cpu\":2.7288860008120537,\"memory\":86.38},{\"round\":1,\"log\":258,\"cpu\":0.12106999941170216,\"memory\":86.45},{\"round\":1,\"log\":259,\"cpu\":6.4634460005909204,\"memory\":79.15},{\"round\":1,\"log\":260,\"cpu\":0.40702799893915653,\"memory\":79.47},{\"round\":1,\"log\":261,\"cpu\":3.6049910001456738,\"memory\":83.33},{\"round\":1,\"log\":262,\"cpu\":0.21130900084972382,\"memory\":83.49},{\"round\":1,\"log\":263,\"cpu\":4.410736998543143,\"memory\":88.01},{\"round\":1,\"log\":264,\"cpu\":0.30286800116300583,\"memory\":88.25},{\"round\":1,\"log\":265,\"cpu\":3.192153999581933,\"memory\":76.87},{\"round\":1,\"log\":266,\"cpu\":0.17911900021135807,\"memory\":76.99},{\"round\":1,\"log\":267,\"cpu\":5.300432000309229,\"memory\":83.32},{\"round\":1,\"log\":268,\"cpu\":0.05477999895811081,\"memory\":83.35},{\"round\":1,\"log\":269,\"cpu\":3.7687610015273094,\"memory\":87.49},{\"round\":1,\"log\":270,\"cpu\":0.03964899852871895,\"memory\":87.51},{\"round\":1,\"log\":271,\"cpu\":5.124053001403809,\"memory\":78.53},{\"round\":1,\"log\":272,\"cpu\":0.05297999829053879,\"memory\":78.56},{\"round\":1,\"log\":273,\"cpu\":2.542797001078725,\"memory\":81.38},{\"round\":1,\"log\":274,\"cpu\":0.037459999322891235,\"memory\":81.39},{\"round\":1,\"log\":275,\"cpu\":5.713770000264049,\"memory\":87.82},{\"round\":1,\"log\":276,\"cpu\":0.06062999926507473,\"memory\":87.85},{\"round\":1,\"log\":277,\"cpu\":5.222723001614213,\"memory\":79.35},{\"round\":1,\"log\":278,\"cpu\":0.04784899950027466,\"memory\":79.37},{\"round\":1,\"log\":279,\"cpu\":4.00415899977088,\"memory\":84.03},{\"round\":1,\"log\":280,\"cpu\":0.05762000009417534,\"memory\":84.06},{\"round\":1,\"log\":281,\"cpu\":2.7643059995025396,\"memory\":86.89},{\"round\":1,\"log\":282,\"cpu\":0.04301000013947487,\"memory\":86.9},{\"round\":1,\"log\":283,\"cpu\":6.291496999561787,\"memory\":79.52},{\"round\":1,\"log\":284,\"cpu\":0.08966900035738945,\"memory\":79.56},{\"round\":1,\"log\":285,\"cpu\":3.9037900008261204,\"memory\":83.71},{\"round\":1,\"log\":286,\"cpu\":0.0569899994879961,\"memory\":83.73},{\"round\":1,\"log\":287,\"cpu\":4.548715999349952,\"memory\":88.39},{\"round\":1,\"log\":288,\"cpu\":0.07542000152170658,\"memory\":88.43},{\"round\":1,\"log\":289,\"cpu\":3.437891999259591,\"memory\":77.56},{\"round\":1,\"log\":290,\"cpu\":0.055630000308156013,\"memory\":77.58},{\"round\":1,\"log\":291,\"cpu\":5.472051000222564,\"memory\":84.01},{\"round\":1,\"log\":292,\"cpu\":0.12113899923861027,\"memory\":84.09},{\"round\":1,\"log\":293,\"cpu\":3.845651000738144,\"memory\":88.23},{\"round\":1,\"log\":294,\"cpu\":0.07283899933099747,\"memory\":88.27},{\"round\":1,\"log\":295,\"cpu\":5.209303000941873,\"memory\":78.92},{\"round\":1,\"log\":296,\"cpu\":0.11766899935901165,\"memory\":78.99},{\"round\":1,\"log\":297,\"cpu\":2.5530270002782345,\"memory\":81.82},{\"round\":1,\"log\":298,\"cpu\":0.06708000041544437,\"memory\":81.85},{\"round\":1,\"log\":299,\"cpu\":4.52874599955976,\"memory\":84.81},{\"round\":1,\"log\":300,\"cpu\":0.19332899898290634,\"memory\":84.89},{\"round\":1,\"log\":301,\"cpu\":0.15465900115668774,\"memory\":84.96},{\"round\":1,\"log\":302,\"cpu\":0.26764899864792824,\"memory\":85.1},{\"round\":1,\"log\":303,\"cpu\":0.2739280015230179,\"memory\":85.24},{\"round\":1,\"log\":304,\"cpu\":0.45815799944102764,\"memory\":85.5},{\"round\":1,\"log\":305,\"cpu\":0.4332779999822378,\"memory\":85.76},{\"round\":1,\"log\":306,\"cpu\":0.8780349995940924,\"memory\":86.28},{\"round\":1,\"log\":307,\"cpu\":0.199498999863863,\"memory\":86.4},{\"round\":1,\"log\":308,\"cpu\":5.727530000731349,\"memory\":78.11},{\"round\":1,\"log\":309,\"cpu\":1.869480999186635,\"memory\":79.83},{\"round\":1,\"log\":310,\"cpu\":4.355707000941038,\"memory\":84.99},{\"round\":1,\"log\":311,\"cpu\":0.9859049990773201,\"memory\":85.97},{\"round\":1,\"log\":312,\"cpu\":5.069364000111818,\"memory\":77.62},{\"round\":1,\"log\":313,\"cpu\":0.8792250007390976,\"memory\":78.49},{\"round\":1,\"log\":314,\"cpu\":4.125668000429869,\"memory\":83.3},{\"round\":1,\"log\":315,\"cpu\":0.7464969996362925,\"memory\":84.16},{\"round\":1,\"log\":316,\"cpu\":16.394244000315666,\"memory\":89.15},{\"round\":1,\"log\":317,\"cpu\":11.149661999195814,\"memory\":89.83},{\"round\":1,\"log\":318,\"cpu\":2.0335300005972385,\"memory\":91.55},{\"round\":1,\"log\":319,\"cpu\":7.063672998920083,\"memory\":86.56},{\"round\":1,\"log\":320,\"cpu\":1.0320350006222725,\"memory\":87.55},{\"round\":1,\"log\":321,\"cpu\":4.197017999365926,\"memory\":92.39},{\"round\":1,\"log\":322,\"cpu\":0.8657950013875961,\"memory\":93.26},{\"round\":1,\"log\":323,\"cpu\":5.003983998671174,\"memory\":84.63},{\"round\":1,\"log\":324,\"cpu\":0.9674450010061264,\"memory\":85.5},{\"round\":1,\"log\":325,\"cpu\":17.018071999773383,\"memory\":93.5},{\"round\":1,\"log\":326,\"cpu\":3.718869999051094,\"memory\":96.27},{\"round\":1,\"log\":327,\"cpu\":5.774190001189709,\"memory\":86.47},{\"round\":1,\"log\":328,\"cpu\":6.818654999136925,\"memory\":90.04},{\"round\":1,\"log\":329,\"cpu\":6.586474999785423,\"memory\":96.91},{\"round\":1,\"log\":330,\"cpu\":2.4112980011850595,\"memory\":85.49},{\"round\":1,\"log\":331,\"cpu\":4.932963998988271,\"memory\":91.32},{\"round\":1,\"log\":332,\"cpu\":1.013085000216961,\"memory\":92.73},{\"round\":1,\"log\":333,\"cpu\":6.187068000435829,\"memory\":87.14},{\"round\":1,\"log\":334,\"cpu\":0.9044949989765882,\"memory\":88.38},{\"round\":1,\"log\":335,\"cpu\":5.861789001151919,\"memory\":94.4},{\"round\":1,\"log\":336,\"cpu\":0.10164999961853027,\"memory\":94.48},{\"round\":1,\"log\":337,\"cpu\":7.490691000595689,\"memory\":88.77},{\"round\":1,\"log\":338,\"cpu\":0.06006000004708767,\"memory\":88.8},{\"round\":1,\"log\":339,\"cpu\":5.081743000075221,\"memory\":94.62},{\"round\":1,\"log\":340,\"cpu\":0.047609999775886536,\"memory\":94.64},{\"round\":1,\"log\":341,\"cpu\":5.7883199993520975,\"memory\":88.16},{\"round\":1,\"log\":342,\"cpu\":0.049140000715851784,\"memory\":88.18},{\"round\":1,\"log\":343,\"cpu\":5.962019000202417,\"memory\":94.21},{\"round\":1,\"log\":344,\"cpu\":0.0978889986872673,\"memory\":94.3},{\"round\":1,\"log\":345,\"cpu\":7.067373000085354,\"memory\":88.66},{\"round\":1,\"log\":346,\"cpu\":0.05557999946177006,\"memory\":88.68},{\"round\":1,\"log\":347,\"cpu\":5.334272000938654,\"memory\":94.51},{\"round\":1,\"log\":348,\"cpu\":0.04611999914050102,\"memory\":94.53},{\"round\":1,\"log\":349,\"cpu\":5.8896690011024475,\"memory\":88.08},{\"round\":1,\"log\":350,\"cpu\":0.04944000020623207,\"memory\":88.1},{\"round\":1,\"log\":351,\"cpu\":6.182757999747992,\"memory\":94.12},{\"round\":1,\"log\":352,\"cpu\":0.0997689999639988,\"memory\":94.2},{\"round\":1,\"log\":353,\"cpu\":7.500630998983979,\"memory\":88.65},{\"round\":1,\"log\":354,\"cpu\":0.06665000133216381,\"memory\":88.68},{\"round\":1,\"log\":355,\"cpu\":5.258863000199199,\"memory\":94.49},{\"round\":1,\"log\":356,\"cpu\":0.11158899962902069,\"memory\":94.58},{\"round\":1,\"log\":357,\"cpu\":5.694160999730229,\"memory\":87.83},{\"round\":1,\"log\":358,\"cpu\":0.18732899986207485,\"memory\":88.01},{\"round\":1,\"log\":359,\"cpu\":5.858218999579549,\"memory\":93.86},{\"round\":1,\"log\":360,\"cpu\":0.09998900070786476,\"memory\":93.95},{\"round\":1,\"log\":361,\"cpu\":7.269553000107408,\"memory\":88.48},{\"round\":1,\"log\":362,\"cpu\":0.0658390000462532,\"memory\":88.51},{\"round\":1,\"log\":363,\"cpu\":5.288943000137806,\"memory\":94.32},{\"round\":1,\"log\":364,\"cpu\":0.1078099999576807,\"memory\":94.41},{\"round\":1,\"log\":365,\"cpu\":6.00190799869597,\"memory\":87.78},{\"round\":1,\"log\":366,\"cpu\":0.18571900017559528,\"memory\":87.95},{\"round\":1,\"log\":367,\"cpu\":5.724130000919104,\"memory\":93.81},{\"round\":1,\"log\":368,\"cpu\":0.20669900067150593,\"memory\":93.94},{\"round\":1,\"log\":369,\"cpu\":7.166542999446392,\"memory\":88.53},{\"round\":1,\"log\":370,\"cpu\":0.09323900006711483,\"memory\":88.58},{\"round\":1,\"log\":371,\"cpu\":5.457812000066042,\"memory\":94.4},{\"round\":1,\"log\":372,\"cpu\":0.15029899962246418,\"memory\":94.56},{\"round\":1,\"log\":373,\"cpu\":5.922198999673128,\"memory\":88.08},{\"round\":1,\"log\":374,\"cpu\":0.2571089994162321,\"memory\":88.39},{\"round\":1,\"log\":375,\"cpu\":6.067738000303507,\"memory\":94.41},{\"round\":1,\"log\":376,\"cpu\":0.18673899956047535,\"memory\":94.54},{\"round\":1,\"log\":377,\"cpu\":7.12589400075376,\"memory\":88.83},{\"round\":1,\"log\":378,\"cpu\":0.10111900046467781,\"memory\":88.88},{\"round\":1,\"log\":379,\"cpu\":5.314051998779178,\"memory\":94.7},{\"round\":1,\"log\":380,\"cpu\":0.14763000048696995,\"memory\":94.86},{\"round\":1,\"log\":381,\"cpu\":5.643510000780225,\"memory\":88.22},{\"round\":1,\"log\":382,\"cpu\":0.2598989997059107,\"memory\":88.53},{\"round\":1,\"log\":383,\"cpu\":6.220828000456095,\"memory\":94.55},{\"round\":1,\"log\":384,\"cpu\":6.967102998867631,\"memory\":84.76},{\"round\":1,\"log\":385,\"cpu\":6.947794001549482,\"memory\":88.33},{\"round\":1,\"log\":386,\"cpu\":0.23022899962961674,\"memory\":88.47},{\"round\":1,\"log\":387,\"cpu\":0.22218899987637997,\"memory\":88.6},{\"round\":1,\"log\":388,\"cpu\":0.20961899869143963,\"memory\":88.74},{\"round\":1,\"log\":389,\"cpu\":0.2186190001666546,\"memory\":88.89},{\"round\":1,\"log\":390,\"cpu\":0.19895900040864944,\"memory\":89.02},{\"round\":1,\"log\":391,\"cpu\":134.21689100004733,\"memory\":42.95},{\"round\":1,\"log\":392,\"cpu\":0.06584000028669834,\"memory\":42.95},{\"round\":1,\"log\":393,\"cpu\":44.55112800002098,\"memory\":56.02},{\"round\":1,\"log\":394,\"cpu\":0.0544000007212162,\"memory\":56.03},{\"round\":1,\"log\":395,\"cpu\":7.25913199968636,\"memory\":51.85},{\"round\":1,\"log\":396,\"cpu\":5.784070000052452,\"memory\":57.89},{\"round\":1,\"log\":397,\"cpu\":3.2358630001544952,\"memory\":51.67},{\"round\":1,\"log\":398,\"cpu\":2.9600839987397194,\"memory\":54.69},{\"round\":1,\"log\":399,\"cpu\":0.5427180007100105,\"memory\":55.25},{\"round\":1,\"log\":400,\"cpu\":3.914750000461936,\"memory\":59.34},{\"round\":1,\"log\":401,\"cpu\":0.8715749997645617,\"memory\":60.11},{\"round\":1,\"log\":402,\"cpu\":1.9962399993091822,\"memory\":62.16},{\"round\":1,\"log\":403,\"cpu\":6.827174000442028,\"memory\":54.83},{\"round\":1,\"log\":404,\"cpu\":1.1502240002155304,\"memory\":55.95},{\"round\":1,\"log\":405,\"cpu\":2.741575999185443,\"memory\":58.97},{\"round\":1,\"log\":406,\"cpu\":0.6092760004103184,\"memory\":59.53},{\"round\":1,\"log\":407,\"cpu\":4.007479999214411,\"memory\":63.62},{\"round\":1,\"log\":408,\"cpu\":0.7735660001635551,\"memory\":64.39},{\"round\":1,\"log\":409,\"cpu\":2.030959000810981,\"memory\":50.74},{\"round\":1,\"log\":410,\"cpu\":0.41674800030887127,\"memory\":51.13},{\"round\":1,\"log\":411,\"cpu\":5.027673998847604,\"memory\":57.17},{\"round\":1,\"log\":412,\"cpu\":1.6023310013115406,\"memory\":58.84},{\"round\":1,\"log\":413,\"cpu\":3.8898499999195337,\"memory\":63.01},{\"round\":1,\"log\":414,\"cpu\":0.8113259989768267,\"memory\":63.76},{\"round\":1,\"log\":415,\"cpu\":4.902693999931216,\"memory\":54.25},{\"round\":1,\"log\":416,\"cpu\":1.2618340011686087,\"memory\":55.43},{\"round\":1,\"log\":417,\"cpu\":2.5687969997525215,\"memory\":58.28},{\"round\":1,\"log\":418,\"cpu\":0.5430669989436865,\"memory\":58.82},{\"round\":1,\"log\":419,\"cpu\":6.383096000179648,\"memory\":53.08},{\"round\":1,\"log\":420,\"cpu\":1.7754710000008345,\"memory\":54.83},{\"round\":1,\"log\":421,\"cpu\":3.664071001112461,\"memory\":59.01},{\"round\":1,\"log\":422,\"cpu\":0.7747259996831417,\"memory\":59.84},{\"round\":1,\"log\":423,\"cpu\":5.580870999023318,\"memory\":52.17},{\"round\":1,\"log\":424,\"cpu\":1.4200330004096031,\"memory\":53.41},{\"round\":1,\"log\":425,\"cpu\":2.6029359996318817,\"memory\":56.26},{\"round\":1,\"log\":426,\"cpu\":0.6665660012513399,\"memory\":56.86},{\"round\":1,\"log\":427,\"cpu\":5.943629998713732,\"memory\":63.3},{\"round\":1,\"log\":428,\"cpu\":0.09755000099539757,\"memory\":63.36},{\"round\":1,\"log\":429,\"cpu\":4.481535999104381,\"memory\":54.6},{\"round\":1,\"log\":430,\"cpu\":0.05449000000953674,\"memory\":54.62},{\"round\":1,\"log\":431,\"cpu\":4.488756000995636,\"memory\":59.27},{\"round\":1,\"log\":432,\"cpu\":0.08366999961435795,\"memory\":59.32},{\"round\":1,\"log\":433,\"cpu\":2.7253259997814894,\"memory\":62.12},{\"round\":1,\"log\":434,\"cpu\":0.04972900077700615,\"memory\":62.14},{\"round\":1,\"log\":435,\"cpu\":6.24944799952209,\"memory\":54.74},{\"round\":1,\"log\":436,\"cpu\":0.14078900031745434,\"memory\":54.83},{\"round\":1,\"log\":437,\"cpu\":3.6987810004502535,\"memory\":58.91},{\"round\":1,\"log\":438,\"cpu\":0.08611899986863136,\"memory\":58.96},{\"round\":1,\"log\":439,\"cpu\":4.415606999769807,\"memory\":63.59},{\"round\":1,\"log\":440,\"cpu\":0.10995000042021275,\"memory\":63.66},{\"round\":1,\"log\":441,\"cpu\":3.146172998473048,\"memory\":52.59},{\"round\":1,\"log\":442,\"cpu\":0.07672000117599964,\"memory\":52.64},{\"round\":1,\"log\":443,\"cpu\":5.3953419998288155,\"memory\":59.04},{\"round\":1,\"log\":444,\"cpu\":0.20644900016486645,\"memory\":59.21},{\"round\":1,\"log\":445,\"cpu\":3.6258209999650717,\"memory\":63.22},{\"round\":1,\"log\":446,\"cpu\":0.11715899966657162,\"memory\":63.31},{\"round\":1,\"log\":447,\"cpu\":5.0306850001215935,\"memory\":53.79},{\"round\":1,\"log\":448,\"cpu\":0.17809899896383286,\"memory\":53.92},{\"round\":1,\"log\":449,\"cpu\":2.4105170015245676,\"memory\":56.65},{\"round\":1,\"log\":450,\"cpu\":0.09596899896860123,\"memory\":56.72},{\"round\":1,\"log\":451,\"cpu\":5.648661000654101,\"memory\":63.1},{\"round\":1,\"log\":452,\"cpu\":0.39893800020217896,\"memory\":63.42},{\"round\":1,\"log\":453,\"cpu\":4.038868999108672,\"memory\":53.9},{\"round\":1,\"log\":454,\"cpu\":0.20516899973154068,\"memory\":54.06},{\"round\":1,\"log\":455,\"cpu\":3.8941000010818243,\"memory\":58.58},{\"round\":1,\"log\":456,\"cpu\":0.2841979991644621,\"memory\":58.81},{\"round\":1,\"log\":457,\"cpu\":2.4204270001500845,\"memory\":61.45},{\"round\":1,\"log\":458,\"cpu\":0.16079900041222572,\"memory\":61.56},{\"round\":1,\"log\":459,\"cpu\":6.177048999816179,\"memory\":54.17},{\"round\":1,\"log\":460,\"cpu\":0.06845900043845177,\"memory\":54.19},{\"round\":1,\"log\":461,\"cpu\":3.6459109988063574,\"memory\":58.34},{\"round\":1,\"log\":462,\"cpu\":0.03764000162482262,\"memory\":58.35},{\"round\":1,\"log\":463,\"cpu\":4.363596998155117,\"memory\":63},{\"round\":1,\"log\":464,\"cpu\":0.04722000099718571,\"memory\":63.03},{\"round\":1,\"log\":465,\"cpu\":3.4606519993394613,\"memory\":52.45},{\"round\":1,\"log\":466,\"cpu\":0.039400000125169754,\"memory\":52.46},{\"round\":1,\"log\":467,\"cpu\":5.419502001255751,\"memory\":58.89},{\"round\":1,\"log\":468,\"cpu\":0.06830899976193905,\"memory\":58.92},{\"round\":1,\"log\":469,\"cpu\":3.844309998676181,\"memory\":63.06},{\"round\":1,\"log\":470,\"cpu\":0.04238000139594078,\"memory\":63.08},{\"round\":1,\"log\":471,\"cpu\":4.639845998957753,\"memory\":53.88},{\"round\":1,\"log\":472,\"cpu\":0.05980000086128712,\"memory\":53.91},{\"round\":1,\"log\":473,\"cpu\":2.5140070002526045,\"memory\":56.74},{\"round\":1,\"log\":474,\"cpu\":0.04615899920463562,\"memory\":56.75},{\"round\":1,\"log\":475,\"cpu\":5.948269000276923,\"memory\":63.18},{\"round\":1,\"log\":476,\"cpu\":0.09397000074386597,\"memory\":63.22},{\"round\":1,\"log\":477,\"cpu\":4.8779439982026815,\"memory\":54.66},{\"round\":1,\"log\":478,\"cpu\":0.0534800011664629,\"memory\":54.69},{\"round\":1,\"log\":479,\"cpu\":4.04050900042057,\"memory\":59.34},{\"round\":1,\"log\":480,\"cpu\":0.06818999908864498,\"memory\":59.38},{\"round\":1,\"log\":481,\"cpu\":2.769275000318885,\"memory\":62.21},{\"round\":1,\"log\":482,\"cpu\":0.04900999926030636,\"memory\":62.23},{\"round\":1,\"log\":483,\"cpu\":6.12733899988234,\"memory\":54.82},{\"round\":1,\"log\":484,\"cpu\":0.11635900102555752,\"memory\":54.89},{\"round\":1,\"log\":485,\"cpu\":3.8556099999696016,\"memory\":59.04},{\"round\":1,\"log\":486,\"cpu\":0.07319900020956993,\"memory\":59.07},{\"round\":1,\"log\":487,\"cpu\":4.549867000430822,\"memory\":63.73},{\"round\":1,\"log\":488,\"cpu\":0.10206899978220463,\"memory\":63.8},{\"round\":1,\"log\":489,\"cpu\":3.617350999265909,\"memory\":52.9},{\"round\":1,\"log\":490,\"cpu\":0.06361999921500683,\"memory\":52.94},{\"round\":1,\"log\":491,\"cpu\":4.5134970005601645,\"memory\":55.88},{\"round\":1,\"log\":492,\"cpu\":0.1965389996767044,\"memory\":55.96},{\"round\":1,\"log\":493,\"cpu\":0.14825900085270405,\"memory\":56.04},{\"round\":1,\"log\":494,\"cpu\":0.2485290002077818,\"memory\":56.18},{\"round\":1,\"log\":495,\"cpu\":0.2360979989171028,\"memory\":56.32},{\"round\":1,\"log\":496,\"cpu\":0.4723780006170273,\"memory\":56.57},{\"round\":1,\"log\":497,\"cpu\":0.4605269990861416,\"memory\":56.83},{\"round\":1,\"log\":498,\"cpu\":0.8412760011851788,\"memory\":57.35},{\"round\":1,\"log\":499,\"cpu\":0.19440899975597858,\"memory\":57.47},{\"round\":1,\"log\":500,\"cpu\":5.13909300044179,\"memory\":62.6},{\"round\":1,\"log\":501,\"cpu\":1.8660809993743896,\"memory\":64.32},{\"round\":1,\"log\":502,\"cpu\":5.355011999607086,\"memory\":54.85},{\"round\":1,\"log\":503,\"cpu\":0.8952649999409914,\"memory\":55.84},{\"round\":1,\"log\":504,\"cpu\":4.043689001351595,\"memory\":60.69},{\"round\":1,\"log\":505,\"cpu\":0.9315749984234571,\"memory\":61.56},{\"round\":1,\"log\":506,\"cpu\":5.278463000431657,\"memory\":53.05},{\"round\":1,\"log\":507,\"cpu\":0.9761950001120567,\"memory\":53.91},{\"round\":1,\"log\":508,\"cpu\":16.488843999803066,\"memory\":61.42},{\"round\":1,\"log\":509,\"cpu\":11.094291999936104,\"memory\":62.22},{\"round\":1,\"log\":510,\"cpu\":2.0543700009584427,\"memory\":63.94},{\"round\":1,\"log\":511,\"cpu\":4.7633449994027615,\"memory\":69.09},{\"round\":1,\"log\":512,\"cpu\":1.0263539999723434,\"memory\":70.08},{\"round\":1,\"log\":513,\"cpu\":5.632641000673175,\"memory\":61.95},{\"round\":1,\"log\":514,\"cpu\":0.868724999949336,\"memory\":62.82},{\"round\":1,\"log\":515,\"cpu\":4.489246999844909,\"memory\":67.63},{\"round\":1,\"log\":516,\"cpu\":0.7936359997838736,\"memory\":68.49},{\"round\":1,\"log\":517,\"cpu\":16.29730499908328,\"memory\":72.72},{\"round\":1,\"log\":518,\"cpu\":6.3439570013433695,\"memory\":68.17},{\"round\":1,\"log\":519,\"cpu\":5.233833000063896,\"memory\":73.29},{\"round\":1,\"log\":520,\"cpu\":9.812978999689221,\"memory\":68.9},{\"round\":1,\"log\":521,\"cpu\":6.928894000127912,\"memory\":75.78},{\"round\":1,\"log\":522,\"cpu\":1.7221609987318516,\"memory\":77.55},{\"round\":1,\"log\":523,\"cpu\":6.541386000812054,\"memory\":71.31},{\"round\":1,\"log\":524,\"cpu\":1.0448650009930134,\"memory\":72.72},{\"round\":1,\"log\":525,\"cpu\":5.25267199985683,\"memory\":78.4},{\"round\":1,\"log\":526,\"cpu\":0.9506349992007017,\"memory\":79.63},{\"round\":1,\"log\":527,\"cpu\":6.57294600084424,\"memory\":72.46},{\"round\":1,\"log\":528,\"cpu\":0.11315899901092052,\"memory\":72.55},{\"round\":1,\"log\":529,\"cpu\":6.481827000156045,\"memory\":79.43},{\"round\":1,\"log\":530,\"cpu\":0.05134999938309193,\"memory\":79.45},{\"round\":1,\"log\":531,\"cpu\":5.640590000897646,\"memory\":72.28},{\"round\":1,\"log\":532,\"cpu\":0.04934000037610531,\"memory\":72.29},{\"round\":1,\"log\":533,\"cpu\":5.028683999553323,\"memory\":77.97},{\"round\":1,\"log\":534,\"cpu\":0.04371899925172329,\"memory\":77.99},{\"round\":1,\"log\":535,\"cpu\":6.66567600145936,\"memory\":71.52},{\"round\":1,\"log\":536,\"cpu\":0.09236999973654747,\"memory\":71.61},{\"round\":1,\"log\":537,\"cpu\":6.377055998891592,\"memory\":78.49},{\"round\":1,\"log\":538,\"cpu\":0.05010000057518482,\"memory\":78.51},{\"round\":1,\"log\":539,\"cpu\":6.092027999460697,\"memory\":71.83},{\"round\":1,\"log\":540,\"cpu\":0.047199999913573265,\"memory\":71.85},{\"round\":1,\"log\":541,\"cpu\":4.91134500131011,\"memory\":77.53},{\"round\":1,\"log\":542,\"cpu\":0.0425299983471632,\"memory\":77.54},{\"round\":1,\"log\":543,\"cpu\":6.850214000791311,\"memory\":71.29},{\"round\":1,\"log\":544,\"cpu\":0.09668900072574615,\"memory\":71.37},{\"round\":1,\"log\":545,\"cpu\":6.485435999929905,\"memory\":78.24},{\"round\":1,\"log\":546,\"cpu\":0.058170000091195107,\"memory\":78.27},{\"round\":1,\"log\":547,\"cpu\":5.988058999180794,\"memory\":71.64},{\"round\":1,\"log\":548,\"cpu\":0.11694999970495701,\"memory\":71.73},{\"round\":1,\"log\":549,\"cpu\":5.063203001394868,\"memory\":77.32},{\"round\":1,\"log\":550,\"cpu\":0.19436899945139885,\"memory\":77.49},{\"round\":1,\"log\":551,\"cpu\":6.638524999842048,\"memory\":70.73},{\"round\":1,\"log\":552,\"cpu\":0.10218000039458275,\"memory\":70.81},{\"round\":1,\"log\":553,\"cpu\":6.441205998882651,\"memory\":77.68},{\"round\":1,\"log\":554,\"cpu\":0.06224000081419945,\"memory\":77.71},{\"round\":1,\"log\":555,\"cpu\":5.928940000012517,\"memory\":71.37},{\"round\":1,\"log\":556,\"cpu\":0.11166900023818016,\"memory\":71.46},{\"round\":1,\"log\":557,\"cpu\":4.963344000279903,\"memory\":77.04},{\"round\":1,\"log\":558,\"cpu\":0.1932389996945858,\"memory\":77.22},{\"round\":1,\"log\":559,\"cpu\":6.5564759988337755,\"memory\":70.58},{\"round\":1,\"log\":560,\"cpu\":0.21415900066494942,\"memory\":70.7},{\"round\":1,\"log\":561,\"cpu\":6.456326000392437,\"memory\":77.58},{\"round\":1,\"log\":562,\"cpu\":0.0837399996817112,\"memory\":77.63},{\"round\":1,\"log\":563,\"cpu\":6.047008000314236,\"memory\":71.33},{\"round\":1,\"log\":564,\"cpu\":0.1503199990838766,\"memory\":71.49},{\"round\":1,\"log\":565,\"cpu\":4.925704000517726,\"memory\":77.17},{\"round\":1,\"log\":566,\"cpu\":0.258457999676466,\"memory\":77.48},{\"round\":1,\"log\":567,\"cpu\":6.786395000293851,\"memory\":71.25},{\"round\":1,\"log\":568,\"cpu\":0.19102000072598457,\"memory\":71.38},{\"round\":1,\"log\":569,\"cpu\":6.559714999049902,\"memory\":78.25},{\"round\":1,\"log\":570,\"cpu\":0.08231000043451786,\"memory\":78.31},{\"round\":1,\"log\":571,\"cpu\":5.98925899900496,\"memory\":71.7},{\"round\":1,\"log\":572,\"cpu\":0.14746900089085102,\"memory\":71.86},{\"round\":1,\"log\":573,\"cpu\":5.114863000810146,\"memory\":77.53},{\"round\":1,\"log\":574,\"cpu\":0.2490289993584156,\"memory\":77.84},{\"round\":1,\"log\":575,\"cpu\":6.656224999576807,\"memory\":71.47},{\"round\":1,\"log\":576,\"cpu\":6.59714600071311,\"memory\":75.02},{\"round\":1,\"log\":577,\"cpu\":6.604256000369787,\"memory\":78.58},{\"round\":1,\"log\":578,\"cpu\":0.22642899863421917,\"memory\":78.72},{\"round\":1,\"log\":579,\"cpu\":0.21830799989402294,\"memory\":78.85},{\"round\":1,\"log\":580,\"cpu\":0.20997900143265724,\"memory\":78.99},{\"round\":1,\"log\":581,\"cpu\":0.21900899894535542,\"memory\":79.14},{\"round\":1,\"log\":582,\"cpu\":0.1999689992517233,\"memory\":79.27},{\"round\":1,\"log\":583,\"cpu\":120.35043400153518,\"memory\":115.92},{\"round\":1,\"log\":584,\"cpu\":0.06293999962508678,\"memory\":115.92},{\"round\":1,\"log\":585,\"cpu\":47.277944000437856,\"memory\":122.09},{\"round\":1,\"log\":586,\"cpu\":0.04869999922811985,\"memory\":122.09},{\"round\":1,\"log\":587,\"cpu\":3.8727889992296696,\"memory\":124.88},{\"round\":1,\"log\":588,\"cpu\":9.121153000742197,\"memory\":124.36},{\"round\":1,\"log\":589,\"cpu\":1.3944930005818605,\"memory\":125.48},{\"round\":1,\"log\":590,\"cpu\":2.8390849996358156,\"memory\":128.5},{\"round\":1,\"log\":591,\"cpu\":0.605816999450326,\"memory\":129.07},{\"round\":1,\"log\":592,\"cpu\":3.9384300000965595,\"memory\":133.16},{\"round\":1,\"log\":593,\"cpu\":0.8603550009429455,\"memory\":133.93},{\"round\":1,\"log\":594,\"cpu\":2.6990959998220205,\"memory\":121.3},{\"round\":1,\"log\":595,\"cpu\":6.381586998701096,\"memory\":127.73},{\"round\":1,\"log\":596,\"cpu\":1.2355830017477274,\"memory\":128.85},{\"round\":1,\"log\":597,\"cpu\":2.620296999812126,\"memory\":131.87},{\"round\":1,\"log\":598,\"cpu\":0.5523169990628958,\"memory\":132.43},{\"round\":1,\"log\":599,\"cpu\":4.640086000785232,\"memory\":122.18},{\"round\":1,\"log\":600,\"cpu\":0.90599500015378,\"memory\":122.95},{\"round\":1,\"log\":601,\"cpu\":1.7814609985798597,\"memory\":125},{\"round\":1,\"log\":602,\"cpu\":0.4024780001491308,\"memory\":125.39},{\"round\":1,\"log\":603,\"cpu\":5.067623000591993,\"memory\":131.42},{\"round\":1,\"log\":604,\"cpu\":1.60984200052917,\"memory\":133.09},{\"round\":1,\"log\":605,\"cpu\":5.069733999669552,\"memory\":125.03},{\"round\":1,\"log\":606,\"cpu\":0.7168959993869066,\"memory\":125.77},{\"round\":1,\"log\":607,\"cpu\":4.107558000832796,\"memory\":130.44},{\"round\":1,\"log\":608,\"cpu\":1.262423999607563,\"memory\":131.63},{\"round\":1,\"log\":609,\"cpu\":2.786904999986291,\"memory\":134.48},{\"round\":1,\"log\":610,\"cpu\":0.6452670004218817,\"memory\":135.01},{\"round\":1,\"log\":611,\"cpu\":6.097707999870181,\"memory\":126.78},{\"round\":1,\"log\":612,\"cpu\":1.9789000004529953,\"memory\":128.53},{\"round\":1,\"log\":613,\"cpu\":4.0213190000504255,\"memory\":132.7},{\"round\":1,\"log\":614,\"cpu\":0.7637759987264872,\"memory\":133.53},{\"round\":1,\"log\":615,\"cpu\":5.589981000870466,\"memory\":124.54},{\"round\":1,\"log\":616,\"cpu\":1.3114429991692305,\"memory\":125.78},{\"round\":1,\"log\":617,\"cpu\":2.602927001193166,\"memory\":128.64},{\"round\":1,\"log\":618,\"cpu\":0.5918069984763861,\"memory\":129.23},{\"round\":1,\"log\":619,\"cpu\":6.841913999989629,\"memory\":123.67},{\"round\":1,\"log\":620,\"cpu\":0.10142000019550323,\"memory\":123.73},{\"round\":1,\"log\":621,\"cpu\":3.724030001088977,\"memory\":127.84},{\"round\":1,\"log\":622,\"cpu\":0.04968000017106533,\"memory\":127.86},{\"round\":1,\"log\":623,\"cpu\":4.371817000210285,\"memory\":132.51},{\"round\":1,\"log\":624,\"cpu\":0.08303999900817871,\"memory\":132.56},{\"round\":1,\"log\":625,\"cpu\":3.3923119995743036,\"memory\":122.52},{\"round\":1,\"log\":626,\"cpu\":0.05519000068306923,\"memory\":122.54},{\"round\":1,\"log\":627,\"cpu\":5.5960809998214245,\"memory\":128.96},{\"round\":1,\"log\":628,\"cpu\":0.1287590004503727,\"memory\":129.05},{\"round\":1,\"log\":629,\"cpu\":3.758321000263095,\"memory\":133.13},{\"round\":1,\"log\":630,\"cpu\":0.08677899837493896,\"memory\":133.18},{\"round\":1,\"log\":631,\"cpu\":4.981584001332521,\"memory\":124.3},{\"round\":1,\"log\":632,\"cpu\":0.1178399994969368,\"memory\":124.37},{\"round\":1,\"log\":633,\"cpu\":2.492305999621749,\"memory\":127.15},{\"round\":1,\"log\":634,\"cpu\":0.07124000042676926,\"memory\":127.19},{\"round\":1,\"log\":635,\"cpu\":5.731189999729395,\"memory\":133.6},{\"round\":1,\"log\":636,\"cpu\":0.21326900087296963,\"memory\":133.76},{\"round\":1,\"log\":637,\"cpu\":5.370492000132799,\"memory\":124.92},{\"round\":1,\"log\":638,\"cpu\":0.12413999997079372,\"memory\":125},{\"round\":1,\"log\":639,\"cpu\":3.9444189984351397,\"memory\":129.59},{\"round\":1,\"log\":640,\"cpu\":0.16402900032699108,\"memory\":129.72},{\"round\":1,\"log\":641,\"cpu\":2.651925999671221,\"memory\":132.45},{\"round\":1,\"log\":642,\"cpu\":0.10838000103831291,\"memory\":132.52},{\"round\":1,\"log\":643,\"cpu\":6.664704998955131,\"memory\":125.23},{\"round\":1,\"log\":644,\"cpu\":0.39594800025224686,\"memory\":125.55},{\"round\":1,\"log\":645,\"cpu\":3.621551001444459,\"memory\":129.41},{\"round\":1,\"log\":646,\"cpu\":0.18941999971866608,\"memory\":129.57},{\"round\":1,\"log\":647,\"cpu\":4.330386999994516,\"memory\":134.09},{\"round\":1,\"log\":648,\"cpu\":0.2850689999759197,\"memory\":134.32},{\"round\":1,\"log\":649,\"cpu\":3.4642209988087416,\"memory\":122.9},{\"round\":1,\"log\":650,\"cpu\":0.15570000000298023,\"memory\":123.02},{\"round\":1,\"log\":651,\"cpu\":5.302442001178861,\"memory\":129.35},{\"round\":1,\"log\":652,\"cpu\":0.04968000017106533,\"memory\":129.37},{\"round\":1,\"log\":653,\"cpu\":3.783040000125766,\"memory\":133.52},{\"round\":1,\"log\":654,\"cpu\":0.03651000000536442,\"memory\":133.53},{\"round\":1,\"log\":655,\"cpu\":5.015023998916149,\"memory\":124.54},{\"round\":1,\"log\":656,\"cpu\":0.04818999953567982,\"memory\":124.56},{\"round\":1,\"log\":657,\"cpu\":2.497427001595497,\"memory\":127.39},{\"round\":1,\"log\":658,\"cpu\":0.03545899875462055,\"memory\":127.4},{\"round\":1,\"log\":659,\"cpu\":5.69875100068748,\"memory\":133.83},{\"round\":1,\"log\":660,\"cpu\":0.056530000641942024,\"memory\":133.86},{\"round\":1,\"log\":661,\"cpu\":5.293001998215914,\"memory\":125.41},{\"round\":1,\"log\":662,\"cpu\":0.0437800008803606,\"memory\":125.42},{\"round\":1,\"log\":663,\"cpu\":3.990778999403119,\"memory\":130.08},{\"round\":1,\"log\":664,\"cpu\":0.0515890009701252,\"memory\":130.11},{\"round\":1,\"log\":665,\"cpu\":2.5801069997251034,\"memory\":132.93},{\"round\":1,\"log\":666,\"cpu\":0.03876999951899052,\"memory\":132.95},{\"round\":1,\"log\":667,\"cpu\":6.090277999639511,\"memory\":125.62},{\"round\":1,\"log\":668,\"cpu\":0.07621000148355961,\"memory\":125.67},{\"round\":1,\"log\":669,\"cpu\":3.9311799984425306,\"memory\":129.82},{\"round\":1,\"log\":670,\"cpu\":0.05151900090277195,\"memory\":129.84},{\"round\":1,\"log\":671,\"cpu\":4.522856999188662,\"memory\":134.5},{\"round\":1,\"log\":672,\"cpu\":0.06763000041246414,\"memory\":134.54},{\"round\":1,\"log\":673,\"cpu\":3.736530000343919,\"memory\":123.64},{\"round\":1,\"log\":674,\"cpu\":0.05030000023543835,\"memory\":123.67},{\"round\":1,\"log\":675,\"cpu\":5.353121999651194,\"memory\":130.09},{\"round\":1,\"log\":676,\"cpu\":0.10143000073730946,\"memory\":130.17},{\"round\":1,\"log\":677,\"cpu\":3.8235189989209175,\"memory\":134.31},{\"round\":1,\"log\":678,\"cpu\":0.07565999962389469,\"memory\":134.35},{\"round\":1,\"log\":679,\"cpu\":4.861565001308918,\"memory\":124.92},{\"round\":1,\"log\":680,\"cpu\":0.10297899879515171,\"memory\":124.99},{\"round\":1,\"log\":681,\"cpu\":2.575407000258565,\"memory\":127.81},{\"round\":1,\"log\":682,\"cpu\":0.06156899966299534,\"memory\":127.84},{\"round\":1,\"log\":683,\"cpu\":4.443548001348972,\"memory\":130.79},{\"round\":1,\"log\":684,\"cpu\":0.18434899859130383,\"memory\":130.86},{\"round\":1,\"log\":685,\"cpu\":0.1565990000963211,\"memory\":130.94},{\"round\":1,\"log\":686,\"cpu\":0.2525290008634329,\"memory\":131.08},{\"round\":1,\"log\":687,\"cpu\":0.24544800072908401,\"memory\":131.22},{\"round\":1,\"log\":688,\"cpu\":0.5157579984515905,\"memory\":131.48},{\"round\":1,\"log\":689,\"cpu\":0.46385700069367886,\"memory\":131.73},{\"round\":1,\"log\":690,\"cpu\":1.0191450007259846,\"memory\":132.29},{\"round\":1,\"log\":691,\"cpu\":0.19830899871885777,\"memory\":132.41},{\"round\":1,\"log\":692,\"cpu\":6.019759001210332,\"memory\":124.13},{\"round\":1,\"log\":693,\"cpu\":1.8366399984806776,\"memory\":125.85},{\"round\":1,\"log\":694,\"cpu\":4.272908000275493,\"memory\":131},{\"round\":1,\"log\":695,\"cpu\":0.9291650000959635,\"memory\":131.99},{\"round\":1,\"log\":696,\"cpu\":5.0019940007478,\"memory\":123.66},{\"round\":1,\"log\":697,\"cpu\":0.8623459991067648,\"memory\":124.53},{\"round\":1,\"log\":698,\"cpu\":3.931579001247883,\"memory\":129.34},{\"round\":1,\"log\":699,\"cpu\":0.7343459986150265,\"memory\":130.2},{\"round\":1,\"log\":700,\"cpu\":16.32815500162542,\"memory\":135.2},{\"round\":1,\"log\":701,\"cpu\":10.91525299847126,\"memory\":135.83},{\"round\":1,\"log\":702,\"cpu\":2.0048600006848574,\"memory\":137.55},{\"round\":1,\"log\":703,\"cpu\":6.711495000869036,\"memory\":132.57},{\"round\":1,\"log\":704,\"cpu\":1.0708949994295835,\"memory\":133.55},{\"round\":1,\"log\":705,\"cpu\":4.199696999043226,\"memory\":138.4},{\"round\":1,\"log\":706,\"cpu\":0.8815060015767813,\"memory\":139.27},{\"round\":1,\"log\":707,\"cpu\":5.035803999751806,\"memory\":130.68},{\"round\":1,\"log\":708,\"cpu\":0.9316549990326166,\"memory\":131.54},{\"round\":1,\"log\":709,\"cpu\":16.572464000433683,\"memory\":139.56},{\"round\":1,\"log\":710,\"cpu\":3.6913099996745586,\"memory\":142.33},{\"round\":1,\"log\":711,\"cpu\":5.885180000215769,\"memory\":132.5},{\"round\":1,\"log\":712,\"cpu\":6.763144999742508,\"memory\":136.06},{\"round\":1,\"log\":713,\"cpu\":6.755485000088811,\"memory\":142.93},{\"round\":1,\"log\":714,\"cpu\":2.482047000899911,\"memory\":131.53},{\"round\":1,\"log\":715,\"cpu\":4.968573998659849,\"memory\":137.35},{\"round\":1,\"log\":716,\"cpu\":1.0003150012344122,\"memory\":138.76},{\"round\":1,\"log\":717,\"cpu\":5.947568999603391,\"memory\":133.22},{\"round\":1,\"log\":718,\"cpu\":0.9291750006377697,\"memory\":134.45},{\"round\":1,\"log\":719,\"cpu\":5.837569998577237,\"memory\":140.47},{\"round\":1,\"log\":720,\"cpu\":0.10641900077462196,\"memory\":140.55},{\"round\":1,\"log\":721,\"cpu\":7.326671998947859,\"memory\":134.84},{\"round\":1,\"log\":722,\"cpu\":0.05745000019669533,\"memory\":134.86},{\"round\":1,\"log\":723,\"cpu\":5.109703000634909,\"memory\":140.69},{\"round\":1,\"log\":724,\"cpu\":0.04480000026524067,\"memory\":140.7},{\"round\":1,\"log\":725,\"cpu\":6.04916900023818,\"memory\":134.19},{\"round\":1,\"log\":726,\"cpu\":0.04810899868607521,\"memory\":134.2},{\"round\":1,\"log\":727,\"cpu\":5.890379000455141,\"memory\":140.22},{\"round\":1,\"log\":728,\"cpu\":0.09139000065624714,\"memory\":140.31},{\"round\":1,\"log\":729,\"cpu\":7.043752999976277,\"memory\":134.72},{\"round\":1,\"log\":730,\"cpu\":0.05137999914586544,\"memory\":134.74},{\"round\":1,\"log\":731,\"cpu\":5.376512000337243,\"memory\":140.57},{\"round\":1,\"log\":732,\"cpu\":0.04323999956250191,\"memory\":140.59},{\"round\":1,\"log\":733,\"cpu\":5.672640001401305,\"memory\":134.16},{\"round\":1,\"log\":734,\"cpu\":0.045049998909235,\"memory\":134.18},{\"round\":1,\"log\":735,\"cpu\":6.05302800051868,\"memory\":140.2},{\"round\":1,\"log\":736,\"cpu\":0.1110800001770258,\"memory\":140.28},{\"round\":1,\"log\":737,\"cpu\":7.309121999889612,\"memory\":134.7},{\"round\":1,\"log\":738,\"cpu\":0.06509999930858612,\"memory\":134.73},{\"round\":1,\"log\":739,\"cpu\":5.15251300111413,\"memory\":140.54},{\"round\":1,\"log\":740,\"cpu\":0.1077089998871088,\"memory\":140.63},{\"round\":1,\"log\":741,\"cpu\":5.577191999182105,\"memory\":133.88},{\"round\":1,\"log\":742,\"cpu\":0.18154899962246418,\"memory\":134.05},{\"round\":1,\"log\":743,\"cpu\":5.965819001197815,\"memory\":139.9},{\"round\":1,\"log\":744,\"cpu\":0.10119899921119213,\"memory\":139.98},{\"round\":1,\"log\":745,\"cpu\":7.172893000766635,\"memory\":134.51},{\"round\":1,\"log\":746,\"cpu\":0.06350899860262871,\"memory\":134.54},{\"round\":1,\"log\":747,\"cpu\":5.26350300014019,\"memory\":140.34},{\"round\":1,\"log\":748,\"cpu\":0.11662900075316429,\"memory\":140.43},{\"round\":1,\"log\":749,\"cpu\":5.951120000332594,\"memory\":133.82},{\"round\":1,\"log\":750,\"cpu\":0.17718899995088577,\"memory\":133.99},{\"round\":1,\"log\":751,\"cpu\":5.76345899887383,\"memory\":139.86},{\"round\":1,\"log\":752,\"cpu\":0.19659900106489658,\"memory\":139.99},{\"round\":1,\"log\":753,\"cpu\":7.3251319993287325,\"memory\":134.6},{\"round\":1,\"log\":754,\"cpu\":0.10518999956548214,\"memory\":134.65},{\"round\":1,\"log\":755,\"cpu\":5.239953000098467,\"memory\":140.47},{\"round\":1,\"log\":756,\"cpu\":0.14238900132477283,\"memory\":140.63},{\"round\":1,\"log\":757,\"cpu\":5.56135099940002,\"memory\":134.18},{\"round\":1,\"log\":758,\"cpu\":0.2602490000426769,\"memory\":134.49},{\"round\":1,\"log\":759,\"cpu\":6.081137999892235,\"memory\":140.52},{\"round\":1,\"log\":760,\"cpu\":0.1869290005415678,\"memory\":140.65},{\"round\":1,\"log\":761,\"cpu\":7.097412999719381,\"memory\":134.86},{\"round\":1,\"log\":762,\"cpu\":0.10455000028014183,\"memory\":134.92},{\"round\":1,\"log\":763,\"cpu\":5.298291999846697,\"memory\":140.74},{\"round\":1,\"log\":764,\"cpu\":0.15065900050103664,\"memory\":140.9},{\"round\":1,\"log\":765,\"cpu\":5.917638998478651,\"memory\":134.25},{\"round\":1,\"log\":766,\"cpu\":0.2577590011060238,\"memory\":134.56},{\"round\":1,\"log\":767,\"cpu\":6.143207998946309,\"memory\":140.58},{\"round\":1,\"log\":768,\"cpu\":7.399512000381947,\"memory\":130.8},{\"round\":1,\"log\":769,\"cpu\":6.468245999887586,\"memory\":134.38},{\"round\":1,\"log\":770,\"cpu\":0.2217590007930994,\"memory\":134.52},{\"round\":1,\"log\":771,\"cpu\":0.21957900002598763,\"memory\":134.65},{\"round\":1,\"log\":772,\"cpu\":0.20593900047242641,\"memory\":134.79},{\"round\":1,\"log\":773,\"cpu\":0.21526899933815002,\"memory\":134.94},{\"round\":1,\"log\":774,\"cpu\":0.19343899935483932,\"memory\":135.07},{\"round\":1,\"log\":775,\"cpu\":119.6067080013454,\"memory\":181.31},{\"round\":1,\"log\":776,\"cpu\":0.06042899936437607,\"memory\":181.31},{\"round\":1,\"log\":777,\"cpu\":46.807537000626326,\"memory\":188.04},{\"round\":1,\"log\":778,\"cpu\":0.06754999980330467,\"memory\":188.04},{\"round\":1,\"log\":779,\"cpu\":6.979253999888897,\"memory\":183.53},{\"round\":1,\"log\":780,\"cpu\":5.585820998996496,\"memory\":189.57},{\"round\":1,\"log\":781,\"cpu\":1.271153001114726,\"memory\":190.69},{\"round\":1,\"log\":782,\"cpu\":2.987994998693466,\"memory\":193.71},{\"round\":1,\"log\":783,\"cpu\":0.5485370010137558,\"memory\":194.27},{\"round\":1,\"log\":784,\"cpu\":5.82442899979651,\"memory\":186.65},{\"round\":1,\"log\":785,\"cpu\":0.8468859996646643,\"memory\":187.43},{\"round\":1,\"log\":786,\"cpu\":2.1215390004217625,\"memory\":189.47},{\"round\":1,\"log\":787,\"cpu\":6.26545700058341,\"memory\":195.9},{\"round\":1,\"log\":788,\"cpu\":1.1067749988287687,\"memory\":197.02},{\"round\":1,\"log\":789,\"cpu\":3.300212999805808,\"memory\":184.94},{\"round\":1,\"log\":790,\"cpu\":0.7040660008788109,\"memory\":185.5},{\"round\":1,\"log\":791,\"cpu\":3.7542499992996454,\"memory\":189.59},{\"round\":1,\"log\":792,\"cpu\":0.7561559993773699,\"memory\":190.36},{\"round\":1,\"log\":793,\"cpu\":1.8048510011285543,\"memory\":192.41},{\"round\":1,\"log\":794,\"cpu\":0.3954280000180006,\"memory\":192.8},{\"round\":1,\"log\":795,\"cpu\":5.841959999874234,\"memory\":185.83},{\"round\":1,\"log\":796,\"cpu\":1.7415709998458624,\"memory\":187.5},{\"round\":1,\"log\":797,\"cpu\":3.72478000074625,\"memory\":191.67},{\"round\":1,\"log\":798,\"cpu\":0.7134959995746613,\"memory\":192.42},{\"round\":1,\"log\":799,\"cpu\":4.096278999000788,\"memory\":197.09},{\"round\":1,\"log\":800,\"cpu\":2.3991480004042387,\"memory\":184.56},{\"round\":1,\"log\":801,\"cpu\":2.743935000151396,\"memory\":187.42},{\"round\":1,\"log\":802,\"cpu\":0.545176999643445,\"memory\":187.95},{\"round\":1,\"log\":803,\"cpu\":5.55337200127542,\"memory\":194.39},{\"round\":1,\"log\":804,\"cpu\":1.8483399990946054,\"memory\":196.14},{\"round\":1,\"log\":805,\"cpu\":4.910594999790192,\"memory\":187.97},{\"round\":1,\"log\":806,\"cpu\":0.7621360011398792,\"memory\":188.8},{\"round\":1,\"log\":807,\"cpu\":4.0909189991652966,\"memory\":193.47},{\"round\":1,\"log\":808,\"cpu\":1.4630219992250204,\"memory\":194.71},{\"round\":1,\"log\":809,\"cpu\":2.831655001267791,\"memory\":197.57},{\"round\":1,\"log\":810,\"cpu\":0.5920869987457991,\"memory\":198.16},{\"round\":1,\"log\":811,\"cpu\":6.127617999911308,\"memory\":189.89},{\"round\":1,\"log\":812,\"cpu\":0.10322000086307526,\"memory\":189.95},{\"round\":1,\"log\":813,\"cpu\":3.9876589998602867,\"memory\":194.06},{\"round\":1,\"log\":814,\"cpu\":0.051510000601410866,\"memory\":194.08},{\"round\":1,\"log\":815,\"cpu\":5.055162999778986,\"memory\":186.21},{\"round\":1,\"log\":816,\"cpu\":0.09489999897778034,\"memory\":186.26},{\"round\":1,\"log\":817,\"cpu\":2.61387600004673,\"memory\":189.06},{\"round\":1,\"log\":818,\"cpu\":0.04757000133395195,\"memory\":189.08},{\"round\":1,\"log\":819,\"cpu\":5.407111998647451,\"memory\":195.5},{\"round\":1,\"log\":820,\"cpu\":0.13000900112092495,\"memory\":195.6},{\"round\":1,\"log\":821,\"cpu\":4.967604000121355,\"memory\":187.5},{\"round\":1,\"log\":822,\"cpu\":0.0937999989837408,\"memory\":187.55},{\"round\":1,\"log\":823,\"cpu\":4.221388000994921,\"memory\":192.18},{\"round\":1,\"log\":824,\"cpu\":0.12798899970948696,\"memory\":192.25},{\"round\":1,\"log\":825,\"cpu\":2.659925999119878,\"memory\":195.03},{\"round\":1,\"log\":826,\"cpu\":0.08159000054001808,\"memory\":195.07},{\"round\":1,\"log\":827,\"cpu\":6.5982460007071495,\"memory\":188.06},{\"round\":1,\"log\":828,\"cpu\":0.21969899907708168,\"memory\":188.23},{\"round\":1,\"log\":829,\"cpu\":3.8595899995416403,\"memory\":192.24},{\"round\":1,\"log\":830,\"cpu\":0.1308390013873577,\"memory\":192.33},{\"round\":1,\"log\":831,\"cpu\":4.345697999000549,\"memory\":196.92},{\"round\":1,\"log\":832,\"cpu\":0.16365900076925755,\"memory\":197.04},{\"round\":1,\"log\":833,\"cpu\":3.872698999941349,\"memory\":186.06},{\"round\":1,\"log\":834,\"cpu\":0.10600000061094761,\"memory\":186.13},{\"round\":1,\"log\":835,\"cpu\":5.349031999707222,\"memory\":192.51},{\"round\":1,\"log\":836,\"cpu\":0.37955799885094166,\"memory\":192.83},{\"round\":1,\"log\":837,\"cpu\":3.590981001034379,\"memory\":196.69},{\"round\":1,\"log\":838,\"cpu\":0.19951899908483028,\"memory\":196.85},{\"round\":1,\"log\":839,\"cpu\":4.856855001300573,\"memory\":187.26},{\"round\":1,\"log\":840,\"cpu\":0.3069579992443323,\"memory\":187.49},{\"round\":1,\"log\":841,\"cpu\":2.352938000112772,\"memory\":190.12},{\"round\":1,\"log\":842,\"cpu\":0.1509189996868372,\"memory\":190.24},{\"round\":1,\"log\":843,\"cpu\":5.718271000310779,\"memory\":196.57},{\"round\":1,\"log\":844,\"cpu\":0.053780000656843185,\"memory\":196.6},{\"round\":1,\"log\":845,\"cpu\":5.184551998972893,\"memory\":188.25},{\"round\":1,\"log\":846,\"cpu\":0.041109999641776085,\"memory\":188.26},{\"round\":1,\"log\":847,\"cpu\":4.00637000054121,\"memory\":192.92},{\"round\":1,\"log\":848,\"cpu\":0.04599899984896183,\"memory\":192.94},{\"round\":1,\"log\":849,\"cpu\":2.656945999711752,\"memory\":195.78},{\"round\":1,\"log\":850,\"cpu\":0.035099999979138374,\"memory\":195.79},{\"round\":1,\"log\":851,\"cpu\":6.402026999741793,\"memory\":188.52},{\"round\":1,\"log\":852,\"cpu\":0.06015999987721443,\"memory\":188.55},{\"round\":1,\"log\":853,\"cpu\":3.9273990001529455,\"memory\":192.69},{\"round\":1,\"log\":854,\"cpu\":0.04398000054061413,\"memory\":192.71},{\"round\":1,\"log\":855,\"cpu\":4.530766999348998,\"memory\":197.36},{\"round\":1,\"log\":856,\"cpu\":0.054559001699090004,\"memory\":197.39},{\"round\":1,\"log\":857,\"cpu\":3.547221999615431,\"memory\":186.55},{\"round\":1,\"log\":858,\"cpu\":0.06154999881982803,\"memory\":186.57},{\"round\":1,\"log\":859,\"cpu\":5.419991001486778,\"memory\":193},{\"round\":1,\"log\":860,\"cpu\":0.07303999923169613,\"memory\":193.04},{\"round\":1,\"log\":861,\"cpu\":3.8592690005898476,\"memory\":197.19},{\"round\":1,\"log\":862,\"cpu\":0.05250000022351742,\"memory\":197.21},{\"round\":1,\"log\":863,\"cpu\":5.212532998993993,\"memory\":187.91},{\"round\":1,\"log\":864,\"cpu\":0.0738500002771616,\"memory\":187.95},{\"round\":1,\"log\":865,\"cpu\":2.5114869996905327,\"memory\":190.78},{\"round\":1,\"log\":866,\"cpu\":0.04660999961197376,\"memory\":190.8},{\"round\":1,\"log\":867,\"cpu\":5.739199999719858,\"memory\":197.23},{\"round\":1,\"log\":868,\"cpu\":0.11980900168418884,\"memory\":197.3},{\"round\":1,\"log\":869,\"cpu\":5.0118339993059635,\"memory\":188.72},{\"round\":1,\"log\":870,\"cpu\":0.06667999923229218,\"memory\":188.76},{\"round\":1,\"log\":871,\"cpu\":3.9640590008348227,\"memory\":193.42},{\"round\":1,\"log\":872,\"cpu\":0.12554999999701977,\"memory\":193.49},{\"round\":1,\"log\":873,\"cpu\":2.824924999848008,\"memory\":196.31},{\"round\":1,\"log\":874,\"cpu\":0.06656000018119812,\"memory\":196.35},{\"round\":1,\"log\":875,\"cpu\":5.280492000281811,\"memory\":185.06},{\"round\":1,\"log\":876,\"cpu\":0.17628899961709976,\"memory\":185.14},{\"round\":1,\"log\":877,\"cpu\":0.15036899968981743,\"memory\":185.22},{\"round\":1,\"log\":878,\"cpu\":0.2450890000909567,\"memory\":185.36},{\"round\":1,\"log\":879,\"cpu\":0.2326890006661415,\"memory\":185.71},{\"round\":1,\"log\":880,\"cpu\":0.422027999535203,\"memory\":185.97},{\"round\":1,\"log\":881,\"cpu\":0.4099279996007681,\"memory\":186.23},{\"round\":1,\"log\":882,\"cpu\":0.8380950000137091,\"memory\":186.75},{\"round\":1,\"log\":883,\"cpu\":0.17704899981617928,\"memory\":186.87},{\"round\":1,\"log\":884,\"cpu\":4.847915001213551,\"memory\":191.99},{\"round\":1,\"log\":885,\"cpu\":2.0533489994704723,\"memory\":193.7},{\"round\":1,\"log\":886,\"cpu\":6.256277998909354,\"memory\":186.38},{\"round\":1,\"log\":887,\"cpu\":1.0365340001881123,\"memory\":187.36},{\"round\":1,\"log\":888,\"cpu\":3.9238300006836653,\"memory\":192.21},{\"round\":1,\"log\":889,\"cpu\":0.755036000162363,\"memory\":193.08},{\"round\":1,\"log\":890,\"cpu\":3.9727890007197857,\"memory\":197.89},{\"round\":1,\"log\":891,\"cpu\":0.7527159992605448,\"memory\":198.75},{\"round\":1,\"log\":892,\"cpu\":18.330424999818206,\"memory\":193.44},{\"round\":1,\"log\":893,\"cpu\":12.204027000814676,\"memory\":194.7},{\"round\":1,\"log\":894,\"cpu\":2.060649000108242,\"memory\":196.42},{\"round\":1,\"log\":895,\"cpu\":4.871834998950362,\"memory\":201.57},{\"round\":1,\"log\":896,\"cpu\":1.0421150010079145,\"memory\":202.55},{\"round\":1,\"log\":897,\"cpu\":5.363561999052763,\"memory\":193.95},{\"round\":1,\"log\":898,\"cpu\":0.9517250005155802,\"memory\":194.82},{\"round\":1,\"log\":899,\"cpu\":4.389206999912858,\"memory\":199.62},{\"round\":1,\"log\":900,\"cpu\":0.7907659988850355,\"memory\":200.48},{\"round\":1,\"log\":901,\"cpu\":16.60636300034821,\"memory\":205.78},{\"round\":1,\"log\":902,\"cpu\":6.940235000103712,\"memory\":201.15},{\"round\":1,\"log\":903,\"cpu\":5.030032999813557,\"memory\":206.27},{\"round\":1,\"log\":904,\"cpu\":6.568136001005769,\"memory\":209.82},{\"round\":1,\"log\":905,\"cpu\":9.096682999283075,\"memory\":207.71},{\"round\":1,\"log\":906,\"cpu\":1.6292509995400906,\"memory\":209.48},{\"round\":1,\"log\":907,\"cpu\":6.4513370003551245,\"memory\":204.2},{\"round\":1,\"log\":908,\"cpu\":1.1259039994329214,\"memory\":205.61},{\"round\":1,\"log\":909,\"cpu\":5.1596330013126135,\"memory\":211.28},{\"round\":1,\"log\":910,\"cpu\":0.8841260001063347,\"memory\":212.51},{\"round\":1,\"log\":911,\"cpu\":7.335911000147462,\"memory\":205.82},{\"round\":1,\"log\":912,\"cpu\":0.11318999901413918,\"memory\":205.9},{\"round\":1,\"log\":913,\"cpu\":6.549266001209617,\"memory\":212.78},{\"round\":1,\"log\":914,\"cpu\":0.05166899971663952,\"memory\":212.8},{\"round\":1,\"log\":915,\"cpu\":6.269058000296354,\"memory\":205.92},{\"round\":1,\"log\":916,\"cpu\":0.04798999987542629,\"memory\":205.94},{\"round\":1,\"log\":917,\"cpu\":5.158642999827862,\"memory\":211.62},{\"round\":1,\"log\":918,\"cpu\":0.04335999861359596,\"memory\":211.63},{\"round\":1,\"log\":919,\"cpu\":6.663335001096129,\"memory\":205.37},{\"round\":1,\"log\":920,\"cpu\":0.09367899969220161,\"memory\":205.45},{\"round\":1,\"log\":921,\"cpu\":6.669276000931859,\"memory\":212.33},{\"round\":1,\"log\":922,\"cpu\":0.05010899901390076,\"memory\":212.35},{\"round\":1,\"log\":923,\"cpu\":6.171969000250101,\"memory\":205.73},{\"round\":1,\"log\":924,\"cpu\":0.0476089995354414,\"memory\":205.74},{\"round\":1,\"log\":925,\"cpu\":5.022064000368118,\"memory\":211.42},{\"round\":1,\"log\":926,\"cpu\":0.04405999928712845,\"memory\":211.43},{\"round\":1,\"log\":927,\"cpu\":6.670225000008941,\"memory\":205.24},{\"round\":1,\"log\":928,\"cpu\":0.09442000091075897,\"memory\":205.31},{\"round\":1,\"log\":929,\"cpu\":6.581655999645591,\"memory\":212.19},{\"round\":1,\"log\":930,\"cpu\":0.060899000614881516,\"memory\":212.22},{\"round\":1,\"log\":931,\"cpu\":5.8878189995884895,\"memory\":205.58},{\"round\":1,\"log\":932,\"cpu\":0.11284000054001808,\"memory\":205.67},{\"round\":1,\"log\":933,\"cpu\":5.0125639997422695,\"memory\":211.26},{\"round\":1,\"log\":934,\"cpu\":0.1828089989721775,\"memory\":211.43},{\"round\":1,\"log\":935,\"cpu\":6.6652550008147955,\"memory\":204.67},{\"round\":1,\"log\":936,\"cpu\":0.10308000072836876,\"memory\":204.75},{\"round\":1,\"log\":937,\"cpu\":6.4364859983325005,\"memory\":211.62},{\"round\":1,\"log\":938,\"cpu\":0.06334000080823898,\"memory\":211.65},{\"round\":1,\"log\":939,\"cpu\":5.938358999788761,\"memory\":205.33},{\"round\":1,\"log\":940,\"cpu\":0.11268999986350536,\"memory\":205.42},{\"round\":1,\"log\":941,\"cpu\":4.989323999732733,\"memory\":211.01},{\"round\":1,\"log\":942,\"cpu\":0.19984900020062923,\"memory\":211.18},{\"round\":1,\"log\":943,\"cpu\":6.50178600102663,\"memory\":204.53},{\"round\":1,\"log\":944,\"cpu\":0.20923899859189987,\"memory\":204.66},{\"round\":1,\"log\":945,\"cpu\":6.594466000795364,\"memory\":211.54},{\"round\":1,\"log\":946,\"cpu\":0.08426900021731853,\"memory\":211.59},{\"round\":1,\"log\":947,\"cpu\":6.141077999025583,\"memory\":205.32},{\"round\":1,\"log\":948,\"cpu\":0.14574900083243847,\"memory\":205.48},{\"round\":1,\"log\":949,\"cpu\":5.090754000470042,\"memory\":211.16},{\"round\":1,\"log\":950,\"cpu\":0.2753289993852377,\"memory\":211.47},{\"round\":1,\"log\":951,\"cpu\":6.809043999761343,\"memory\":205.26},{\"round\":1,\"log\":952,\"cpu\":0.1899190004914999,\"memory\":205.38},{\"round\":1,\"log\":953,\"cpu\":6.584955999627709,\"memory\":212.26},{\"round\":1,\"log\":954,\"cpu\":0.08306900039315224,\"memory\":212.31},{\"round\":1,\"log\":955,\"cpu\":6.0819589998573065,\"memory\":205.67},{\"round\":1,\"log\":956,\"cpu\":0.15213900059461594,\"memory\":205.83},{\"round\":1,\"log\":957,\"cpu\":4.971163999289274,\"memory\":211.51},{\"round\":1,\"log\":958,\"cpu\":0.23979900032281876,\"memory\":211.82},{\"round\":1,\"log\":959,\"cpu\":6.778415000066161,\"memory\":205.44},{\"round\":1,\"log\":960,\"cpu\":6.837983999401331,\"memory\":208.99},{\"round\":1,\"log\":961,\"cpu\":6.761135000735521,\"memory\":212.55},{\"round\":1,\"log\":962,\"cpu\":0.23005899973213673,\"memory\":212.69},{\"round\":1,\"log\":963,\"cpu\":0.22229900024831295,\"memory\":212.83},{\"round\":1,\"log\":964,\"cpu\":0.213298998773098,\"memory\":212.96},{\"round\":1,\"log\":965,\"cpu\":0.22360900044441223,\"memory\":213.11},{\"round\":1,\"log\":966,\"cpu\":0.19969800114631653,\"memory\":213.25},{\"round\":1,\"log\":967,\"cpu\":161.6372999995947,\"memory\":41.36},{\"round\":1,\"log\":968,\"cpu\":0.07345999963581562,\"memory\":41.36},{\"round\":1,\"log\":969,\"cpu\":47.028954999521375,\"memory\":52.23},{\"round\":1,\"log\":970,\"cpu\":0.06410999968647957,\"memory\":52.23}],[{\"round\":2,\"log\":0,\"cpu\":18.17539600096643,\"memory\":10.45},{\"round\":2,\"log\":1,\"cpu\":2.086208999156952,\"memory\":11.7},{\"round\":2,\"log\":2,\"cpu\":0.6403970010578632,\"memory\":11.71},{\"round\":2,\"log\":3,\"cpu\":0.3157679997384548,\"memory\":11.74},{\"round\":2,\"log\":4,\"cpu\":0.15811899863183498,\"memory\":11.75},{\"round\":2,\"log\":5,\"cpu\":0.11591000109910965,\"memory\":11.77},{\"round\":2,\"log\":6,\"cpu\":0.058960000053048134,\"memory\":11.78},{\"round\":2,\"log\":7,\"cpu\":0.36472800001502037,\"memory\":11.91},{\"round\":2,\"log\":8,\"cpu\":0.11876899935305119,\"memory\":11.93},{\"round\":2,\"log\":9,\"cpu\":0.19657899998128414,\"memory\":11.99},{\"round\":2,\"log\":10,\"cpu\":0.10405899956822395,\"memory\":12.01},{\"round\":2,\"log\":11,\"cpu\":1.8115210011601448,\"memory\":13.47},{\"round\":2,\"log\":12,\"cpu\":11.323811000213027,\"memory\":6.98},{\"round\":2,\"log\":13,\"cpu\":1.4854419995099306,\"memory\":8.1},{\"round\":2,\"log\":14,\"cpu\":4.062588999047875,\"memory\":11.22},{\"round\":2,\"log\":15,\"cpu\":0.8953160010278225,\"memory\":11.78},{\"round\":2,\"log\":16,\"cpu\":5.090583000332117,\"memory\":15.95},{\"round\":2,\"log\":17,\"cpu\":2.2523589991033077,\"memory\":4.38},{\"round\":2,\"log\":18,\"cpu\":2.4989570006728172,\"memory\":6.48},{\"round\":2,\"log\":19,\"cpu\":6.999133000150323,\"memory\":12.98},{\"round\":2,\"log\":20,\"cpu\":1.3653729986399412,\"memory\":14.1},{\"round\":2,\"log\":21,\"cpu\":3.3319830000400543,\"memory\":17.16},{\"round\":2,\"log\":22,\"cpu\":0.631496001034975,\"memory\":17.72},{\"round\":2,\"log\":23,\"cpu\":4.730666000396013,\"memory\":6.22},{\"round\":2,\"log\":24,\"cpu\":0.9417249988764524,\"memory\":6.99},{\"round\":2,\"log\":25,\"cpu\":2.2426680009812117,\"memory\":9.08},{\"round\":2,\"log\":26,\"cpu\":0.47450799867510796,\"memory\":9.47},{\"round\":2,\"log\":27,\"cpu\":5.91732900030911,\"memory\":15.53},{\"round\":2,\"log\":28,\"cpu\":2.286167999729514,\"memory\":17.24},{\"round\":2,\"log\":29,\"cpu\":5.685911001637578,\"memory\":8.72},{\"round\":2,\"log\":30,\"cpu\":0.8323649987578392,\"memory\":9.49},{\"round\":2,\"log\":31,\"cpu\":5.085774000734091,\"memory\":14.31},{\"round\":2,\"log\":32,\"cpu\":1.552912000566721,\"memory\":15.55},{\"round\":2,\"log\":33,\"cpu\":4.008638998493552,\"memory\":5.38},{\"round\":2,\"log\":34,\"cpu\":0.6921970006078482,\"memory\":5.93},{\"round\":2,\"log\":35,\"cpu\":6.772603999823332,\"memory\":12.55},{\"round\":2,\"log\":36,\"cpu\":2.139578999951482,\"memory\":14.34},{\"round\":2,\"log\":37,\"cpu\":5.79437000118196,\"memory\":6.95},{\"round\":2,\"log\":38,\"cpu\":0.9325849991291761,\"memory\":7.79},{\"round\":2,\"log\":39,\"cpu\":4.69365599937737,\"memory\":12.5},{\"round\":2,\"log\":40,\"cpu\":1.5775910001248121,\"memory\":13.77},{\"round\":2,\"log\":41,\"cpu\":3.002665000036359,\"memory\":16.63},{\"round\":2,\"log\":42,\"cpu\":0.7755159996449947,\"memory\":17.22},{\"round\":2,\"log\":43,\"cpu\":6.75526500120759,\"memory\":9.11},{\"round\":2,\"log\":44,\"cpu\":0.13932899944484234,\"memory\":9.17},{\"round\":2,\"log\":45,\"cpu\":4.302068000659347,\"memory\":13.29},{\"round\":2,\"log\":46,\"cpu\":0.05819899961352348,\"memory\":13.31},{\"round\":2,\"log\":47,\"cpu\":5.582691000774503,\"memory\":5.64},{\"round\":2,\"log\":48,\"cpu\":0.1469389982521534,\"memory\":5.69},{\"round\":2,\"log\":49,\"cpu\":2.810546001419425,\"memory\":8.49},{\"round\":2,\"log\":50,\"cpu\":0.053039999678730965,\"memory\":8.51},{\"round\":2,\"log\":51,\"cpu\":5.796939998865128,\"memory\":14.94},{\"round\":2,\"log\":52,\"cpu\":0.16889900155365467,\"memory\":15.04},{\"round\":2,\"log\":53,\"cpu\":5.496110999956727,\"memory\":7.04},{\"round\":2,\"log\":54,\"cpu\":0.10853999853134155,\"memory\":7.09},{\"round\":2,\"log\":55,\"cpu\":4.4881060011684895,\"memory\":11.74},{\"round\":2,\"log\":56,\"cpu\":0.1496500000357628,\"memory\":11.82},{\"round\":2,\"log\":57,\"cpu\":2.801655000075698,\"memory\":14.6},{\"round\":2,\"log\":58,\"cpu\":0.09117900021374226,\"memory\":14.63},{\"round\":2,\"log\":59,\"cpu\":6.680185999721289,\"memory\":7.67},{\"round\":2,\"log\":60,\"cpu\":0.24288900010287762,\"memory\":7.85},{\"round\":2,\"log\":61,\"cpu\":3.963078999891877,\"memory\":11.86},{\"round\":2,\"log\":62,\"cpu\":0.1417789999395609,\"memory\":11.96},{\"round\":2,\"log\":63,\"cpu\":4.579306999221444,\"memory\":16.58},{\"round\":2,\"log\":64,\"cpu\":0.2069490011781454,\"memory\":16.7},{\"round\":2,\"log\":65,\"cpu\":3.49881099909544,\"memory\":5.71},{\"round\":2,\"log\":66,\"cpu\":0.13063899986445904,\"memory\":5.77},{\"round\":2,\"log\":67,\"cpu\":5.512641999870539,\"memory\":12.16},{\"round\":2,\"log\":68,\"cpu\":0.39935800060629845,\"memory\":12.48},{\"round\":2,\"log\":69,\"cpu\":3.7486300002783537,\"memory\":16.36},{\"round\":2,\"log\":70,\"cpu\":0.22838899865746498,\"memory\":16.52},{\"round\":2,\"log\":71,\"cpu\":4.978645000606775,\"memory\":6.95},{\"round\":2,\"log\":72,\"cpu\":0.3416179995983839,\"memory\":7.18},{\"round\":2,\"log\":73,\"cpu\":2.4479470010846853,\"memory\":9.82},{\"round\":2,\"log\":74,\"cpu\":0.1844289992004633,\"memory\":9.93},{\"round\":2,\"log\":75,\"cpu\":5.811280000954866,\"memory\":16.27},{\"round\":2,\"log\":76,\"cpu\":0.07889899984002113,\"memory\":16.3},{\"round\":2,\"log\":77,\"cpu\":4.848664999008179,\"memory\":7.96},{\"round\":2,\"log\":78,\"cpu\":0.04231000132858753,\"memory\":7.98},{\"round\":2,\"log\":79,\"cpu\":4.199647998437285,\"memory\":12.66},{\"round\":2,\"log\":80,\"cpu\":0.05294000171124935,\"memory\":12.69},{\"round\":2,\"log\":81,\"cpu\":2.821774998679757,\"memory\":15.51},{\"round\":2,\"log\":82,\"cpu\":0.04028000123798847,\"memory\":15.52},{\"round\":2,\"log\":83,\"cpu\":6.29942699894309,\"memory\":8.23},{\"round\":2,\"log\":84,\"cpu\":0.0657999999821186,\"memory\":8.26},{\"round\":2,\"log\":85,\"cpu\":3.9395100008696318,\"memory\":12.41},{\"round\":2,\"log\":86,\"cpu\":0.05015899986028671,\"memory\":12.43},{\"round\":2,\"log\":87,\"cpu\":4.806104999035597,\"memory\":17.14},{\"round\":2,\"log\":88,\"cpu\":0.06651000119745731,\"memory\":17.17},{\"round\":2,\"log\":89,\"cpu\":3.3808229994028807,\"memory\":6.28},{\"round\":2,\"log\":90,\"cpu\":0.06142899952828884,\"memory\":6.3},{\"round\":2,\"log\":91,\"cpu\":5.420692000538111,\"memory\":12.73},{\"round\":2,\"log\":92,\"cpu\":0.07913899980485439,\"memory\":12.78},{\"round\":2,\"log\":93,\"cpu\":3.8199499994516373,\"memory\":16.93},{\"round\":2,\"log\":94,\"cpu\":0.05503000132739544,\"memory\":16.95},{\"round\":2,\"log\":95,\"cpu\":4.780024999752641,\"memory\":7.63},{\"round\":2,\"log\":96,\"cpu\":0.09643999859690666,\"memory\":7.67},{\"round\":2,\"log\":97,\"cpu\":2.572477001696825,\"memory\":10.5},{\"round\":2,\"log\":98,\"cpu\":0.052518999204039574,\"memory\":10.52},{\"round\":2,\"log\":99,\"cpu\":5.84273000061512,\"memory\":16.96},{\"round\":2,\"log\":100,\"cpu\":0.12031899951398373,\"memory\":17.04},{\"round\":2,\"log\":101,\"cpu\":4.5829869993031025,\"memory\":8.41},{\"round\":2,\"log\":102,\"cpu\":0.06958900019526482,\"memory\":8.45},{\"round\":2,\"log\":103,\"cpu\":4.121837999671698,\"memory\":13.13},{\"round\":2,\"log\":104,\"cpu\":0.1068700011819601,\"memory\":13.2},{\"round\":2,\"log\":105,\"cpu\":2.749185999855399,\"memory\":16.02},{\"round\":2,\"log\":106,\"cpu\":0.06917900033295155,\"memory\":16.06},{\"round\":2,\"log\":107,\"cpu\":5.4764820002019405,\"memory\":4.83},{\"round\":2,\"log\":108,\"cpu\":0.20269900001585484,\"memory\":4.91},{\"round\":2,\"log\":109,\"cpu\":0.15782899968326092,\"memory\":4.99},{\"round\":2,\"log\":110,\"cpu\":0.2515389993786812,\"memory\":5.13},{\"round\":2,\"log\":111,\"cpu\":0.2366380002349615,\"memory\":5.26},{\"round\":2,\"log\":112,\"cpu\":0.4543280005455017,\"memory\":5.52},{\"round\":2,\"log\":113,\"cpu\":0.4936269987374544,\"memory\":5.78},{\"round\":2,\"log\":114,\"cpu\":0.8801659997552633,\"memory\":6.3},{\"round\":2,\"log\":115,\"cpu\":0.18861900083720684,\"memory\":6.42},{\"round\":2,\"log\":116,\"cpu\":5.140033999457955,\"memory\":11.59},{\"round\":2,\"log\":117,\"cpu\":2.0290290005505085,\"memory\":13.31},{\"round\":2,\"log\":118,\"cpu\":6.127048000693321,\"memory\":5.97},{\"round\":2,\"log\":119,\"cpu\":1.0839049983769655,\"memory\":6.96},{\"round\":2,\"log\":120,\"cpu\":4.267037000507116,\"memory\":11.83},{\"round\":2,\"log\":121,\"cpu\":0.7602260001003742,\"memory\":12.7},{\"round\":2,\"log\":122,\"cpu\":4.232747999951243,\"memory\":17.52},{\"round\":2,\"log\":123,\"cpu\":0.7898559998720884,\"memory\":18.38},{\"round\":2,\"log\":124,\"cpu\":19.0398409999907,\"memory\":13.17},{\"round\":2,\"log\":125,\"cpu\":12.302226999774575,\"memory\":14.44},{\"round\":2,\"log\":126,\"cpu\":2.0424990002065897,\"memory\":16.16},{\"round\":2,\"log\":127,\"cpu\":4.630806000903249,\"memory\":21.32},{\"round\":2,\"log\":128,\"cpu\":0.9236949998885393,\"memory\":22.3},{\"round\":2,\"log\":129,\"cpu\":5.21637300029397,\"memory\":13.76},{\"round\":2,\"log\":130,\"cpu\":1.0205639991909266,\"memory\":14.64},{\"round\":2,\"log\":131,\"cpu\":4.504657000303268,\"memory\":19.44},{\"round\":2,\"log\":132,\"cpu\":0.8178460001945496,\"memory\":20.3},{\"round\":2,\"log\":133,\"cpu\":17.508359000086784,\"memory\":25.56},{\"round\":2,\"log\":134,\"cpu\":5.5635909996926785,\"memory\":20.96},{\"round\":2,\"log\":135,\"cpu\":5.105773000046611,\"memory\":26.07},{\"round\":2,\"log\":136,\"cpu\":6.832644999027252,\"memory\":29.71},{\"round\":2,\"log\":137,\"cpu\":8.308257000520825,\"memory\":27.71},{\"round\":2,\"log\":138,\"cpu\":1.5635420009493828,\"memory\":29.49},{\"round\":2,\"log\":139,\"cpu\":6.487815998494625,\"memory\":24.06},{\"round\":2,\"log\":140,\"cpu\":1.1121440008282661,\"memory\":25.48},{\"round\":2,\"log\":141,\"cpu\":4.637366000562906,\"memory\":31.15},{\"round\":2,\"log\":142,\"cpu\":0.8811459988355637,\"memory\":32.38},{\"round\":2,\"log\":143,\"cpu\":7.126462999731302,\"memory\":25.59},{\"round\":2,\"log\":144,\"cpu\":0.11605900153517723,\"memory\":25.68},{\"round\":2,\"log\":145,\"cpu\":6.442405998706818,\"memory\":32.56},{\"round\":2,\"log\":146,\"cpu\":0.051740000024437904,\"memory\":32.58},{\"round\":2,\"log\":147,\"cpu\":6.251248000189662,\"memory\":25.7},{\"round\":2,\"log\":148,\"cpu\":0.04933900013566017,\"memory\":25.71},{\"round\":2,\"log\":149,\"cpu\":5.522102000191808,\"memory\":31.39},{\"round\":2,\"log\":150,\"cpu\":0.04392999969422817,\"memory\":31.41},{\"round\":2,\"log\":151,\"cpu\":6.597775001078844,\"memory\":25.04},{\"round\":2,\"log\":152,\"cpu\":0.09781000018119812,\"memory\":25.13},{\"round\":2,\"log\":153,\"cpu\":6.749354999512434,\"memory\":32.01},{\"round\":2,\"log\":154,\"cpu\":0.05274000018835068,\"memory\":32.03},{\"round\":2,\"log\":155,\"cpu\":6.151657000184059,\"memory\":25.37},{\"round\":2,\"log\":156,\"cpu\":0.05274999886751175,\"memory\":25.38},{\"round\":2,\"log\":157,\"cpu\":5.148903001099825,\"memory\":31.06},{\"round\":2,\"log\":158,\"cpu\":0.04413999989628792,\"memory\":31.07},{\"round\":2,\"log\":159,\"cpu\":6.9746139999479055,\"memory\":24.88},{\"round\":2,\"log\":160,\"cpu\":0.10988999903202057,\"memory\":24.95},{\"round\":2,\"log\":161,\"cpu\":6.876764001324773,\"memory\":31.83},{\"round\":2,\"log\":162,\"cpu\":0.06807899847626686,\"memory\":31.86},{\"round\":2,\"log\":163,\"cpu\":5.9672090001404285,\"memory\":25.23},{\"round\":2,\"log\":164,\"cpu\":0.12099000066518784,\"memory\":25.32},{\"round\":2,\"log\":165,\"cpu\":5.166262999176979,\"memory\":30.91},{\"round\":2,\"log\":166,\"cpu\":0.1878490000963211,\"memory\":31.09},{\"round\":2,\"log\":167,\"cpu\":6.9828240014612675,\"memory\":24.3},{\"round\":2,\"log\":168,\"cpu\":0.10899899899959564,\"memory\":24.38},{\"round\":2,\"log\":169,\"cpu\":6.646715000271797,\"memory\":31.25},{\"round\":2,\"log\":170,\"cpu\":0.06265000067651272,\"memory\":31.28},{\"round\":2,\"log\":171,\"cpu\":5.974858999252319,\"memory\":24.94},{\"round\":2,\"log\":172,\"cpu\":0.1099299993366003,\"memory\":25.03},{\"round\":2,\"log\":173,\"cpu\":4.995582999661565,\"memory\":30.62},{\"round\":2,\"log\":174,\"cpu\":0.19718900136649609,\"memory\":30.79},{\"round\":2,\"log\":175,\"cpu\":6.654285999014974,\"memory\":24.15},{\"round\":2,\"log\":176,\"cpu\":0.21357900090515614,\"memory\":24.27},{\"round\":2,\"log\":177,\"cpu\":6.62317599914968,\"memory\":31.15},{\"round\":2,\"log\":178,\"cpu\":0.08656900003552437,\"memory\":31.2},{\"round\":2,\"log\":179,\"cpu\":6.201928000897169,\"memory\":24.95},{\"round\":2,\"log\":180,\"cpu\":0.14906900003552437,\"memory\":25.11},{\"round\":2,\"log\":181,\"cpu\":5.106753999367356,\"memory\":30.78},{\"round\":2,\"log\":182,\"cpu\":0.2787580005824566,\"memory\":31.09},{\"round\":2,\"log\":183,\"cpu\":6.821255000308156,\"memory\":24.9},{\"round\":2,\"log\":184,\"cpu\":0.190158998593688,\"memory\":25.02},{\"round\":2,\"log\":185,\"cpu\":6.7643040008842945,\"memory\":31.9},{\"round\":2,\"log\":186,\"cpu\":0.0843299999833107,\"memory\":31.95},{\"round\":2,\"log\":187,\"cpu\":5.794309999793768,\"memory\":25.37},{\"round\":2,\"log\":188,\"cpu\":0.15752900019288063,\"memory\":25.53},{\"round\":2,\"log\":189,\"cpu\":5.092844000086188,\"memory\":31.2},{\"round\":2,\"log\":190,\"cpu\":0.2480079997330904,\"memory\":31.51},{\"round\":2,\"log\":191,\"cpu\":6.605706000700593,\"memory\":25.12},{\"round\":2,\"log\":192,\"cpu\":7.190702999010682,\"memory\":28.75},{\"round\":2,\"log\":193,\"cpu\":6.8647039998322725,\"memory\":32.35},{\"round\":2,\"log\":194,\"cpu\":0.2277090009301901,\"memory\":32.49},{\"round\":2,\"log\":195,\"cpu\":0.2173089999705553,\"memory\":32.62},{\"round\":2,\"log\":196,\"cpu\":0.21168899908661842,\"memory\":32.76},{\"round\":2,\"log\":197,\"cpu\":0.2170289997011423,\"memory\":32.91},{\"round\":2,\"log\":198,\"cpu\":0.1947290003299713,\"memory\":33.04},{\"round\":2,\"log\":199,\"cpu\":121.5321479998529,\"memory\":69.81},{\"round\":2,\"log\":200,\"cpu\":0.06080999970436096,\"memory\":69.82},{\"round\":2,\"log\":201,\"cpu\":47.66355200111866,\"memory\":76.01},{\"round\":2,\"log\":202,\"cpu\":0.05946999974548817,\"memory\":76.01},{\"round\":2,\"log\":203,\"cpu\":3.9090999998152256,\"memory\":78.79},{\"round\":2,\"log\":204,\"cpu\":8.366046000272036,\"memory\":78.19},{\"round\":2,\"log\":205,\"cpu\":1.3835729993879795,\"memory\":79.31},{\"round\":2,\"log\":206,\"cpu\":2.8685849998146296,\"memory\":82.33},{\"round\":2,\"log\":207,\"cpu\":0.666856000199914,\"memory\":82.89},{\"round\":2,\"log\":208,\"cpu\":4.02326900139451,\"memory\":86.98},{\"round\":2,\"log\":209,\"cpu\":1.0296649988740683,\"memory\":87.75},{\"round\":2,\"log\":210,\"cpu\":2.6230769995599985,\"memory\":75.25},{\"round\":2,\"log\":211,\"cpu\":6.1874270010739565,\"memory\":81.68},{\"round\":2,\"log\":212,\"cpu\":1.4393130000680685,\"memory\":82.8},{\"round\":2,\"log\":213,\"cpu\":2.6078169997781515,\"memory\":85.82},{\"round\":2,\"log\":214,\"cpu\":0.5981360003352165,\"memory\":86.38},{\"round\":2,\"log\":215,\"cpu\":4.548007000237703,\"memory\":76.07},{\"round\":2,\"log\":216,\"cpu\":0.9093749988824129,\"memory\":76.84},{\"round\":2,\"log\":217,\"cpu\":1.7762509994208813,\"memory\":78.89},{\"round\":2,\"log\":218,\"cpu\":0.39617800153791904,\"memory\":79.27},{\"round\":2,\"log\":219,\"cpu\":5.039622999727726,\"memory\":85.31},{\"round\":2,\"log\":220,\"cpu\":1.6660619992762804,\"memory\":86.99},{\"round\":2,\"log\":221,\"cpu\":4.909624001011252,\"memory\":78.9},{\"round\":2,\"log\":222,\"cpu\":0.7205870002508163,\"memory\":79.65},{\"round\":2,\"log\":223,\"cpu\":4.1567479986697435,\"memory\":84.35},{\"round\":2,\"log\":224,\"cpu\":1.3303430005908012,\"memory\":85.56},{\"round\":2,\"log\":225,\"cpu\":2.8566049989312887,\"memory\":88.41},{\"round\":2,\"log\":226,\"cpu\":0.6753270011395216,\"memory\":88.94},{\"round\":2,\"log\":227,\"cpu\":6.131107999011874,\"memory\":80.68},{\"round\":2,\"log\":228,\"cpu\":2.0068500004708767,\"memory\":82.44},{\"round\":2,\"log\":229,\"cpu\":4.040479000657797,\"memory\":86.62},{\"round\":2,\"log\":230,\"cpu\":0.8156949989497662,\"memory\":87.45},{\"round\":2,\"log\":231,\"cpu\":5.073694000020623,\"memory\":78.41},{\"round\":2,\"log\":232,\"cpu\":1.3853530008345842,\"memory\":79.66},{\"round\":2,\"log\":233,\"cpu\":2.601425999775529,\"memory\":82.51},{\"round\":2,\"log\":234,\"cpu\":0.6094470005482435,\"memory\":83.1},{\"round\":2,\"log\":235,\"cpu\":6.756005000323057,\"memory\":77.51},{\"round\":2,\"log\":236,\"cpu\":0.10953999869525433,\"memory\":77.57},{\"round\":2,\"log\":237,\"cpu\":3.709640000015497,\"memory\":81.69},{\"round\":2,\"log\":238,\"cpu\":0.05016000010073185,\"memory\":81.71},{\"round\":2,\"log\":239,\"cpu\":4.409127000719309,\"memory\":86.39},{\"round\":2,\"log\":240,\"cpu\":0.10688900016248226,\"memory\":86.43},{\"round\":2,\"log\":241,\"cpu\":3.935539999976754,\"memory\":76.34},{\"round\":2,\"log\":242,\"cpu\":0.05574999935925007,\"memory\":76.36},{\"round\":2,\"log\":243,\"cpu\":5.550261000171304,\"memory\":82.78},{\"round\":2,\"log\":244,\"cpu\":0.13281900063157082,\"memory\":82.88},{\"round\":2,\"log\":245,\"cpu\":3.7262709997594357,\"memory\":86.96},{\"round\":2,\"log\":246,\"cpu\":0.09750999882817268,\"memory\":87.01},{\"round\":2,\"log\":247,\"cpu\":5.161052001640201,\"memory\":78.06},{\"round\":2,\"log\":248,\"cpu\":0.13526999950408936,\"memory\":78.13},{\"round\":2,\"log\":249,\"cpu\":2.5140070002526045,\"memory\":80.91},{\"round\":2,\"log\":250,\"cpu\":0.07682899944484234,\"memory\":80.95},{\"round\":2,\"log\":251,\"cpu\":5.886309999972582,\"memory\":87.35},{\"round\":2,\"log\":252,\"cpu\":0.22182800062000751,\"memory\":87.52},{\"round\":2,\"log\":253,\"cpu\":4.728736000135541,\"memory\":78.67},{\"round\":2,\"log\":254,\"cpu\":0.1305689997971058,\"memory\":78.76},{\"round\":2,\"log\":255,\"cpu\":4.0177189987152815,\"memory\":83.38},{\"round\":2,\"log\":256,\"cpu\":0.18120899982750416,\"memory\":83.5},{\"round\":2,\"log\":257,\"cpu\":2.6294770017266273,\"memory\":86.23},{\"round\":2,\"log\":258,\"cpu\":0.11697899922728539,\"memory\":86.29},{\"round\":2,\"log\":259,\"cpu\":6.36990699917078,\"memory\":79.04},{\"round\":2,\"log\":260,\"cpu\":0.40064800158143044,\"memory\":79.37},{\"round\":2,\"log\":261,\"cpu\":3.4898819997906685,\"memory\":83.23},{\"round\":2,\"log\":262,\"cpu\":0.2053490001708269,\"memory\":83.4},{\"round\":2,\"log\":263,\"cpu\":4.305186999961734,\"memory\":87.94},{\"round\":2,\"log\":264,\"cpu\":0.3099289983510971,\"memory\":88.17},{\"round\":2,\"log\":265,\"cpu\":3.440532000735402,\"memory\":76.67},{\"round\":2,\"log\":266,\"cpu\":0.16876900009810925,\"memory\":76.79},{\"round\":2,\"log\":267,\"cpu\":5.240753000602126,\"memory\":83.13},{\"round\":2,\"log\":268,\"cpu\":0.050919000059366226,\"memory\":83.16},{\"round\":2,\"log\":269,\"cpu\":3.810480998829007,\"memory\":87.31},{\"round\":2,\"log\":270,\"cpu\":0.038100000470876694,\"memory\":87.32},{\"round\":2,\"log\":271,\"cpu\":5.07774299941957,\"memory\":78.34},{\"round\":2,\"log\":272,\"cpu\":0.06462999992072582,\"memory\":78.37},{\"round\":2,\"log\":273,\"cpu\":2.5469960011541843,\"memory\":81.19},{\"round\":2,\"log\":274,\"cpu\":0.03507000021636486,\"memory\":81.2},{\"round\":2,\"log\":275,\"cpu\":5.745880998671055,\"memory\":87.63},{\"round\":2,\"log\":276,\"cpu\":0.069649001583457,\"memory\":87.66},{\"round\":2,\"log\":277,\"cpu\":5.4269319996237755,\"memory\":79.18},{\"round\":2,\"log\":278,\"cpu\":0.04569999873638153,\"memory\":79.2},{\"round\":2,\"log\":279,\"cpu\":4.01039900071919,\"memory\":83.88},{\"round\":2,\"log\":280,\"cpu\":0.05925000086426735,\"memory\":83.91},{\"round\":2,\"log\":281,\"cpu\":2.674625998362899,\"memory\":86.73},{\"round\":2,\"log\":282,\"cpu\":0.042639000341296196,\"memory\":86.74},{\"round\":2,\"log\":283,\"cpu\":6.167929001152515,\"memory\":79.42},{\"round\":2,\"log\":284,\"cpu\":0.0771189983934164,\"memory\":79.46},{\"round\":2,\"log\":285,\"cpu\":3.8646100014448166,\"memory\":83.61},{\"round\":2,\"log\":286,\"cpu\":0.05528999865055084,\"memory\":83.64},{\"round\":2,\"log\":287,\"cpu\":4.543535999953747,\"memory\":88.32},{\"round\":2,\"log\":288,\"cpu\":0.0711200013756752,\"memory\":88.36},{\"round\":2,\"log\":289,\"cpu\":3.7564399987459183,\"memory\":77.48},{\"round\":2,\"log\":290,\"cpu\":0.051990000531077385,\"memory\":77.5},{\"round\":2,\"log\":291,\"cpu\":5.36782200075686,\"memory\":83.93},{\"round\":2,\"log\":292,\"cpu\":0.11603999882936478,\"memory\":84.01},{\"round\":2,\"log\":293,\"cpu\":3.754270000383258,\"memory\":88.16},{\"round\":2,\"log\":294,\"cpu\":0.06852000020444393,\"memory\":88.19},{\"round\":2,\"log\":295,\"cpu\":5.069273000583053,\"memory\":78.78},{\"round\":2,\"log\":296,\"cpu\":0.11613999865949154,\"memory\":78.85},{\"round\":2,\"log\":297,\"cpu\":2.595966000109911,\"memory\":81.68},{\"round\":2,\"log\":298,\"cpu\":0.06338000111281872,\"memory\":81.71},{\"round\":2,\"log\":299,\"cpu\":4.48819600045681,\"memory\":84.71},{\"round\":2,\"log\":300,\"cpu\":0.18987899832427502,\"memory\":84.79},{\"round\":2,\"log\":301,\"cpu\":0.1639800015836954,\"memory\":84.87},{\"round\":2,\"log\":302,\"cpu\":0.281267998740077,\"memory\":85.01},{\"round\":2,\"log\":303,\"cpu\":0.2643290013074875,\"memory\":85.14},{\"round\":2,\"log\":304,\"cpu\":0.48348699882626534,\"memory\":85.4},{\"round\":2,\"log\":305,\"cpu\":0.46963800117373466,\"memory\":85.66},{\"round\":2,\"log\":306,\"cpu\":0.9530849996954203,\"memory\":86.18},{\"round\":2,\"log\":307,\"cpu\":0.1951889991760254,\"memory\":86.3},{\"round\":2,\"log\":308,\"cpu\":5.778880000114441,\"memory\":78},{\"round\":2,\"log\":309,\"cpu\":1.8385899998247623,\"memory\":79.72},{\"round\":2,\"log\":310,\"cpu\":4.315208001062274,\"memory\":84.88},{\"round\":2,\"log\":311,\"cpu\":1.0134649984538555,\"memory\":85.86},{\"round\":2,\"log\":312,\"cpu\":5.087433001026511,\"memory\":77.46},{\"round\":2,\"log\":313,\"cpu\":0.8451659996062517,\"memory\":78.33},{\"round\":2,\"log\":314,\"cpu\":4.137788999825716,\"memory\":83.13},{\"round\":2,\"log\":315,\"cpu\":0.7342760004103184,\"memory\":83.99},{\"round\":2,\"log\":316,\"cpu\":16.444444000720978,\"memory\":88.98},{\"round\":2,\"log\":317,\"cpu\":11.286162000149488,\"memory\":89.66},{\"round\":2,\"log\":318,\"cpu\":1.9642599988728762,\"memory\":91.37},{\"round\":2,\"log\":319,\"cpu\":6.665565000846982,\"memory\":86.37},{\"round\":2,\"log\":320,\"cpu\":1.0136350002139807,\"memory\":87.35},{\"round\":2,\"log\":321,\"cpu\":4.336926998570561,\"memory\":92.19},{\"round\":2,\"log\":322,\"cpu\":0.876315001398325,\"memory\":93.07},{\"round\":2,\"log\":323,\"cpu\":5.381702998653054,\"memory\":84.47},{\"round\":2,\"log\":324,\"cpu\":0.9649050012230873,\"memory\":85.33},{\"round\":2,\"log\":325,\"cpu\":17.02187099866569,\"memory\":93.36},{\"round\":2,\"log\":326,\"cpu\":3.7772110011428595,\"memory\":96.13},{\"round\":2,\"log\":327,\"cpu\":5.525630999356508,\"memory\":86.3},{\"round\":2,\"log\":328,\"cpu\":6.792835000902414,\"memory\":89.88},{\"round\":2,\"log\":329,\"cpu\":6.843063998967409,\"memory\":96.75},{\"round\":2,\"log\":330,\"cpu\":2.681056000292301,\"memory\":85.34},{\"round\":2,\"log\":331,\"cpu\":4.914555000141263,\"memory\":91.17},{\"round\":2,\"log\":332,\"cpu\":1.0064739994704723,\"memory\":92.58},{\"round\":2,\"log\":333,\"cpu\":5.879520000889897,\"memory\":87.01},{\"round\":2,\"log\":334,\"cpu\":0.9046649988740683,\"memory\":88.24},{\"round\":2,\"log\":335,\"cpu\":5.958429001271725,\"memory\":94.26},{\"round\":2,\"log\":336,\"cpu\":0.11304999887943268,\"memory\":94.35},{\"round\":2,\"log\":337,\"cpu\":7.550280001014471,\"memory\":88.62},{\"round\":2,\"log\":338,\"cpu\":0.06708999909460545,\"memory\":88.64},{\"round\":2,\"log\":339,\"cpu\":5.2283929996192455,\"memory\":94.46},{\"round\":2,\"log\":340,\"cpu\":0.04565900005400181,\"memory\":94.48},{\"round\":2,\"log\":341,\"cpu\":5.91363999992609,\"memory\":87.96},{\"round\":2,\"log\":342,\"cpu\":0.04796000011265278,\"memory\":87.97},{\"round\":2,\"log\":343,\"cpu\":5.934899000450969,\"memory\":93.99},{\"round\":2,\"log\":344,\"cpu\":0.09991900064051151,\"memory\":94.08},{\"round\":2,\"log\":345,\"cpu\":7.273372000083327,\"memory\":88.5},{\"round\":2,\"log\":346,\"cpu\":0.050279999151825905,\"memory\":88.52},{\"round\":2,\"log\":347,\"cpu\":5.279442999511957,\"memory\":94.35},{\"round\":2,\"log\":348,\"cpu\":0.04446000047028065,\"memory\":94.36},{\"round\":2,\"log\":349,\"cpu\":5.836689000949264,\"memory\":87.91},{\"round\":2,\"log\":350,\"cpu\":0.04478999972343445,\"memory\":87.93},{\"round\":2,\"log\":351,\"cpu\":6.149917999282479,\"memory\":93.95},{\"round\":2,\"log\":352,\"cpu\":0.09796999953687191,\"memory\":94.03},{\"round\":2,\"log\":353,\"cpu\":7.25917199999094,\"memory\":88.48},{\"round\":2,\"log\":354,\"cpu\":0.06344000063836575,\"memory\":88.51},{\"round\":2,\"log\":355,\"cpu\":5.1673530004918575,\"memory\":94.32},{\"round\":2,\"log\":356,\"cpu\":0.10886899940669537,\"memory\":94.41},{\"round\":2,\"log\":357,\"cpu\":5.9822390004992485,\"memory\":87.65},{\"round\":2,\"log\":358,\"cpu\":0.19249900057911873,\"memory\":87.82},{\"round\":2,\"log\":359,\"cpu\":5.898548999801278,\"memory\":93.67},{\"round\":2,\"log\":360,\"cpu\":0.1006499994546175,\"memory\":93.75},{\"round\":2,\"log\":361,\"cpu\":7.18580299988389,\"memory\":88.36},{\"round\":2,\"log\":362,\"cpu\":0.06372899934649467,\"memory\":88.39},{\"round\":2,\"log\":363,\"cpu\":5.343553001061082,\"memory\":94.2},{\"round\":2,\"log\":364,\"cpu\":0.12123899906873703,\"memory\":94.29},{\"round\":2,\"log\":365,\"cpu\":5.607661001384258,\"memory\":87.63},{\"round\":2,\"log\":366,\"cpu\":0.18010899983346462,\"memory\":87.8},{\"round\":2,\"log\":367,\"cpu\":5.882118999958038,\"memory\":93.66},{\"round\":2,\"log\":368,\"cpu\":0.19747900031507015,\"memory\":93.79},{\"round\":2,\"log\":369,\"cpu\":7.261102998629212,\"memory\":88.37},{\"round\":2,\"log\":370,\"cpu\":0.0944990012794733,\"memory\":88.42},{\"round\":2,\"log\":371,\"cpu\":5.217662999406457,\"memory\":94.25},{\"round\":2,\"log\":372,\"cpu\":0.15517899952828884,\"memory\":94.41},{\"round\":2,\"log\":373,\"cpu\":5.629150999709964,\"memory\":87.93},{\"round\":2,\"log\":374,\"cpu\":0.24720900133252144,\"memory\":88.24},{\"round\":2,\"log\":375,\"cpu\":6.094477999955416,\"memory\":94.26},{\"round\":2,\"log\":376,\"cpu\":0.17957899905741215,\"memory\":94.39},{\"round\":2,\"log\":377,\"cpu\":7.223283000290394,\"memory\":88.69},{\"round\":2,\"log\":378,\"cpu\":0.0866289995610714,\"memory\":88.74},{\"round\":2,\"log\":379,\"cpu\":5.006574001163244,\"memory\":94.57},{\"round\":2,\"log\":380,\"cpu\":0.14000899903476238,\"memory\":94.73},{\"round\":2,\"log\":381,\"cpu\":5.634401999413967,\"memory\":88.11},{\"round\":2,\"log\":382,\"cpu\":0.24912800081074238,\"memory\":88.42},{\"round\":2,\"log\":383,\"cpu\":5.895289000123739,\"memory\":94.44},{\"round\":2,\"log\":384,\"cpu\":7.2038429994136095,\"memory\":84.67},{\"round\":2,\"log\":385,\"cpu\":6.576596001163125,\"memory\":88.23},{\"round\":2,\"log\":386,\"cpu\":0.22170899994671345,\"memory\":88.36},{\"round\":2,\"log\":387,\"cpu\":0.2111590001732111,\"memory\":88.5},{\"round\":2,\"log\":388,\"cpu\":0.20554899983108044,\"memory\":88.64},{\"round\":2,\"log\":389,\"cpu\":0.21394899860024452,\"memory\":88.79},{\"round\":2,\"log\":390,\"cpu\":0.19179899990558624,\"memory\":88.92},{\"round\":2,\"log\":391,\"cpu\":135.40952600166202,\"memory\":42.77},{\"round\":2,\"log\":392,\"cpu\":0.06410999968647957,\"memory\":42.78},{\"round\":2,\"log\":393,\"cpu\":42.99993699975312,\"memory\":55.68},{\"round\":2,\"log\":394,\"cpu\":0.05579899996519089,\"memory\":55.68},{\"round\":2,\"log\":395,\"cpu\":6.262437999248505,\"memory\":51.31},{\"round\":2,\"log\":396,\"cpu\":5.700629999861121,\"memory\":57.35},{\"round\":2,\"log\":397,\"cpu\":1.2424740009009838,\"memory\":58.47},{\"round\":2,\"log\":398,\"cpu\":4.168717999011278,\"memory\":51.13},{\"round\":2,\"log\":399,\"cpu\":0.6510870009660721,\"memory\":51.69},{\"round\":2,\"log\":400,\"cpu\":3.8700600005686283,\"memory\":55.78},{\"round\":2,\"log\":401,\"cpu\":0.9480649996548891,\"memory\":56.55},{\"round\":2,\"log\":402,\"cpu\":1.9347789995372295,\"memory\":58.6},{\"round\":2,\"log\":403,\"cpu\":7.3387529999017715,\"memory\":52.97},{\"round\":2,\"log\":404,\"cpu\":1.530960999429226,\"memory\":54.09},{\"round\":2,\"log\":405,\"cpu\":2.543247001245618,\"memory\":57.11},{\"round\":2,\"log\":406,\"cpu\":0.5652569998055696,\"memory\":57.67},{\"round\":2,\"log\":407,\"cpu\":3.4767019990831614,\"memory\":61.76},{\"round\":2,\"log\":408,\"cpu\":0.7865260001271963,\"memory\":62.53},{\"round\":2,\"log\":409,\"cpu\":2.2610790003091097,\"memory\":49.76},{\"round\":2,\"log\":410,\"cpu\":0.47592700086534023,\"memory\":50.15},{\"round\":2,\"log\":411,\"cpu\":5.017864000052214,\"memory\":56.18},{\"round\":2,\"log\":412,\"cpu\":1.8917399998754263,\"memory\":57.86},{\"round\":2,\"log\":413,\"cpu\":4.192788999527693,\"memory\":62.03},{\"round\":2,\"log\":414,\"cpu\":0.8789849989116192,\"memory\":62.79},{\"round\":2,\"log\":415,\"cpu\":5.162143001332879,\"memory\":53.74},{\"round\":2,\"log\":416,\"cpu\":1.3559329994022846,\"memory\":54.95},{\"round\":2,\"log\":417,\"cpu\":2.6352270003408194,\"memory\":57.8},{\"round\":2,\"log\":418,\"cpu\":0.5805169995874166,\"memory\":58.33},{\"round\":2,\"log\":419,\"cpu\":6.737104000523686,\"memory\":52.77},{\"round\":2,\"log\":420,\"cpu\":1.8086210004985332,\"memory\":54.52},{\"round\":2,\"log\":421,\"cpu\":3.6766009982675314,\"memory\":58.7},{\"round\":2,\"log\":422,\"cpu\":0.8654550015926361,\"memory\":59.54},{\"round\":2,\"log\":423,\"cpu\":4.494836999103427,\"memory\":64.23},{\"round\":2,\"log\":424,\"cpu\":2.0576399993151426,\"memory\":51.76},{\"round\":2,\"log\":425,\"cpu\":2.6427960004657507,\"memory\":54.61},{\"round\":2,\"log\":426,\"cpu\":0.6081560011953115,\"memory\":55.2},{\"round\":2,\"log\":427,\"cpu\":6.048318998888135,\"memory\":61.64},{\"round\":2,\"log\":428,\"cpu\":0.10940000042319298,\"memory\":61.71},{\"round\":2,\"log\":429,\"cpu\":4.899243999272585,\"memory\":53.75},{\"round\":2,\"log\":430,\"cpu\":0.05615000054240227,\"memory\":53.77},{\"round\":2,\"log\":431,\"cpu\":4.077809000387788,\"memory\":58.44},{\"round\":2,\"log\":432,\"cpu\":0.09528899937868118,\"memory\":58.49},{\"round\":2,\"log\":433,\"cpu\":2.6005070004612207,\"memory\":61.28},{\"round\":2,\"log\":434,\"cpu\":0.04876899905502796,\"memory\":61.3},{\"round\":2,\"log\":435,\"cpu\":6.52203700132668,\"memory\":54.31},{\"round\":2,\"log\":436,\"cpu\":0.14256899990141392,\"memory\":54.41},{\"round\":2,\"log\":437,\"cpu\":3.894209999591112,\"memory\":58.49},{\"round\":2,\"log\":438,\"cpu\":0.09279900044202805,\"memory\":58.54},{\"round\":2,\"log\":439,\"cpu\":4.446007000282407,\"memory\":63.19},{\"round\":2,\"log\":440,\"cpu\":0.1300089992582798,\"memory\":63.26},{\"round\":2,\"log\":441,\"cpu\":3.856690000742674,\"memory\":52.4},{\"round\":2,\"log\":442,\"cpu\":0.0818599984049797,\"memory\":52.44},{\"round\":2,\"log\":443,\"cpu\":5.287132000550628,\"memory\":58.85},{\"round\":2,\"log\":444,\"cpu\":0.20120899938046932,\"memory\":59.02},{\"round\":2,\"log\":445,\"cpu\":3.7599410004913807,\"memory\":63.03},{\"round\":2,\"log\":446,\"cpu\":0.16121900081634521,\"memory\":63.12},{\"round\":2,\"log\":447,\"cpu\":5.068714000284672,\"memory\":53.68},{\"round\":2,\"log\":448,\"cpu\":0.18824899941682816,\"memory\":53.8},{\"round\":2,\"log\":449,\"cpu\":2.4453170001506805,\"memory\":56.53},{\"round\":2,\"log\":450,\"cpu\":0.10683999955654144,\"memory\":56.59},{\"round\":2,\"log\":451,\"cpu\":5.743789000436664,\"memory\":62.98},{\"round\":2,\"log\":452,\"cpu\":0.4270379990339279,\"memory\":63.3},{\"round\":2,\"log\":453,\"cpu\":4.519447000697255,\"memory\":53.81},{\"round\":2,\"log\":454,\"cpu\":0.21378899924457073,\"memory\":53.97},{\"round\":2,\"log\":455,\"cpu\":3.9676090013235807,\"memory\":58.52},{\"round\":2,\"log\":456,\"cpu\":0.304967999458313,\"memory\":58.75},{\"round\":2,\"log\":457,\"cpu\":2.492528000846505,\"memory\":61.38},{\"round\":2,\"log\":458,\"cpu\":0.16342899948358536,\"memory\":61.49},{\"round\":2,\"log\":459,\"cpu\":6.532406000420451,\"memory\":54.13},{\"round\":2,\"log\":460,\"cpu\":0.07700899988412857,\"memory\":54.16},{\"round\":2,\"log\":461,\"cpu\":3.692290998995304,\"memory\":58.31},{\"round\":2,\"log\":462,\"cpu\":0.0366200003772974,\"memory\":58.32},{\"round\":2,\"log\":463,\"cpu\":4.4733569994568825,\"memory\":63},{\"round\":2,\"log\":464,\"cpu\":0.04887999966740608,\"memory\":63.02},{\"round\":2,\"log\":465,\"cpu\":3.4796810001134872,\"memory\":52.39},{\"round\":2,\"log\":466,\"cpu\":0.03740000165998936,\"memory\":52.4},{\"round\":2,\"log\":467,\"cpu\":5.33619299903512,\"memory\":58.83},{\"round\":2,\"log\":468,\"cpu\":0.05656000040471554,\"memory\":58.86},{\"round\":2,\"log\":469,\"cpu\":3.908179000020027,\"memory\":63.01},{\"round\":2,\"log\":470,\"cpu\":0.04243999905884266,\"memory\":63.03},{\"round\":2,\"log\":471,\"cpu\":5.01150400005281,\"memory\":53.86},{\"round\":2,\"log\":472,\"cpu\":0.05712000094354153,\"memory\":53.89},{\"round\":2,\"log\":473,\"cpu\":2.5489859990775585,\"memory\":56.71},{\"round\":2,\"log\":474,\"cpu\":0.03942999988794327,\"memory\":56.72},{\"round\":2,\"log\":475,\"cpu\":5.651731001213193,\"memory\":63.16},{\"round\":2,\"log\":476,\"cpu\":0.08284899964928627,\"memory\":63.2},{\"round\":2,\"log\":477,\"cpu\":5.0887439996004105,\"memory\":54.6},{\"round\":2,\"log\":478,\"cpu\":0.05481000058352947,\"memory\":54.63},{\"round\":2,\"log\":479,\"cpu\":4.229327999055386,\"memory\":59.33},{\"round\":2,\"log\":480,\"cpu\":0.07369900122284889,\"memory\":59.37},{\"round\":2,\"log\":481,\"cpu\":2.8042759988456964,\"memory\":62.19},{\"round\":2,\"log\":482,\"cpu\":0.05233000032603741,\"memory\":62.21},{\"round\":2,\"log\":483,\"cpu\":6.373106000944972,\"memory\":54.81},{\"round\":2,\"log\":484,\"cpu\":0.12108999863266945,\"memory\":54.89},{\"round\":2,\"log\":485,\"cpu\":3.9285690002143383,\"memory\":59.04},{\"round\":2,\"log\":486,\"cpu\":0.07101999968290329,\"memory\":59.08},{\"round\":2,\"log\":487,\"cpu\":4.4967760015279055,\"memory\":63.76},{\"round\":2,\"log\":488,\"cpu\":0.10339999943971634,\"memory\":63.83},{\"round\":2,\"log\":489,\"cpu\":3.7511609997600317,\"memory\":52.93},{\"round\":2,\"log\":490,\"cpu\":0.06512900069355965,\"memory\":52.96},{\"round\":2,\"log\":491,\"cpu\":4.61506599932909,\"memory\":56.11},{\"round\":2,\"log\":492,\"cpu\":0.20040900073945522,\"memory\":56.19},{\"round\":2,\"log\":493,\"cpu\":0.15299899876117706,\"memory\":56.26},{\"round\":2,\"log\":494,\"cpu\":0.24571900069713593,\"memory\":56.4},{\"round\":2,\"log\":495,\"cpu\":0.29038799926638603,\"memory\":56.55},{\"round\":2,\"log\":496,\"cpu\":0.44275799952447414,\"memory\":56.8},{\"round\":2,\"log\":497,\"cpu\":0.41397800110280514,\"memory\":57.07},{\"round\":2,\"log\":498,\"cpu\":0.8282859995961189,\"memory\":57.59},{\"round\":2,\"log\":499,\"cpu\":0.19607900083065033,\"memory\":57.71},{\"round\":2,\"log\":500,\"cpu\":5.0968539994210005,\"memory\":62.83},{\"round\":2,\"log\":501,\"cpu\":1.9797690007835627,\"memory\":64.55},{\"round\":2,\"log\":502,\"cpu\":5.0037239994853735,\"memory\":55.06},{\"round\":2,\"log\":503,\"cpu\":0.9068250004202127,\"memory\":56.04},{\"round\":2,\"log\":504,\"cpu\":4.0130989998579025,\"memory\":60.89},{\"round\":2,\"log\":505,\"cpu\":0.9265059996396303,\"memory\":61.77},{\"round\":2,\"log\":506,\"cpu\":5.035064000636339,\"memory\":53.18},{\"round\":2,\"log\":507,\"cpu\":0.9456449989229441,\"memory\":54.04},{\"round\":2,\"log\":508,\"cpu\":16.964842000976205,\"memory\":61.56},{\"round\":2,\"log\":509,\"cpu\":11.119322000071406,\"memory\":62.37},{\"round\":2,\"log\":510,\"cpu\":2.1165289990603924,\"memory\":64.09},{\"round\":2,\"log\":511,\"cpu\":4.7421749997884035,\"memory\":69.25},{\"round\":2,\"log\":512,\"cpu\":1.0281950011849403,\"memory\":70.23},{\"round\":2,\"log\":513,\"cpu\":5.422111999243498,\"memory\":62.1},{\"round\":2,\"log\":514,\"cpu\":0.9156149998307228,\"memory\":62.98},{\"round\":2,\"log\":515,\"cpu\":3.8774900007992983,\"memory\":67.78},{\"round\":2,\"log\":516,\"cpu\":0.7321759983897209,\"memory\":68.64},{\"round\":2,\"log\":517,\"cpu\":16.03834700025618,\"memory\":72.84},{\"round\":2,\"log\":518,\"cpu\":5.652180001139641,\"memory\":68.3},{\"round\":2,\"log\":519,\"cpu\":4.973454998806119,\"memory\":73.41},{\"round\":2,\"log\":520,\"cpu\":8.685615001246333,\"memory\":69.05},{\"round\":2,\"log\":521,\"cpu\":6.834333999082446,\"memory\":75.93},{\"round\":2,\"log\":522,\"cpu\":1.7483510002493858,\"memory\":77.7},{\"round\":2,\"log\":523,\"cpu\":6.879024000838399,\"memory\":71.46},{\"round\":2,\"log\":524,\"cpu\":1.0497650001198053,\"memory\":72.87},{\"round\":2,\"log\":525,\"cpu\":4.845294998958707,\"memory\":78.65},{\"round\":2,\"log\":526,\"cpu\":0.9093149993568659,\"memory\":79.88},{\"round\":2,\"log\":527,\"cpu\":6.597756000235677,\"memory\":72.76},{\"round\":2,\"log\":528,\"cpu\":0.1111490000039339,\"memory\":72.85},{\"round\":2,\"log\":529,\"cpu\":6.52751599997282,\"memory\":79.73},{\"round\":2,\"log\":530,\"cpu\":0.049630001187324524,\"memory\":79.75},{\"round\":2,\"log\":531,\"cpu\":5.615751000121236,\"memory\":72.6},{\"round\":2,\"log\":532,\"cpu\":0.04642999917268753,\"memory\":72.61},{\"round\":2,\"log\":533,\"cpu\":5.019173000007868,\"memory\":78.29},{\"round\":2,\"log\":534,\"cpu\":0.042729999870061874,\"memory\":78.3},{\"round\":2,\"log\":535,\"cpu\":6.454497000202537,\"memory\":71.87},{\"round\":2,\"log\":536,\"cpu\":0.0969190001487732,\"memory\":71.96},{\"round\":2,\"log\":537,\"cpu\":6.412737000733614,\"memory\":78.84},{\"round\":2,\"log\":538,\"cpu\":0.04940999858081341,\"memory\":78.86},{\"round\":2,\"log\":539,\"cpu\":6.007888000458479,\"memory\":72.11},{\"round\":2,\"log\":540,\"cpu\":0.047129999846220016,\"memory\":72.12},{\"round\":2,\"log\":541,\"cpu\":4.95333500020206,\"memory\":77.8},{\"round\":2,\"log\":542,\"cpu\":0.042639000341296196,\"memory\":77.81},{\"round\":2,\"log\":543,\"cpu\":6.77373499982059,\"memory\":71.61},{\"round\":2,\"log\":544,\"cpu\":0.09624999947845936,\"memory\":71.69},{\"round\":2,\"log\":545,\"cpu\":6.4964359998703,\"memory\":78.56},{\"round\":2,\"log\":546,\"cpu\":0.05650000087916851,\"memory\":78.59},{\"round\":2,\"log\":547,\"cpu\":5.9893890004605055,\"memory\":71.9},{\"round\":2,\"log\":548,\"cpu\":0.11442899890244007,\"memory\":71.99},{\"round\":2,\"log\":549,\"cpu\":4.951824000105262,\"memory\":77.58},{\"round\":2,\"log\":550,\"cpu\":0.20404900051653385,\"memory\":77.76},{\"round\":2,\"log\":551,\"cpu\":6.456716999411583,\"memory\":71},{\"round\":2,\"log\":552,\"cpu\":0.10609900020062923,\"memory\":71.08},{\"round\":2,\"log\":553,\"cpu\":6.433077000081539,\"memory\":77.95},{\"round\":2,\"log\":554,\"cpu\":0.06313900090754032,\"memory\":77.98},{\"round\":2,\"log\":555,\"cpu\":6.09124899841845,\"memory\":71.61},{\"round\":2,\"log\":556,\"cpu\":0.11065900139510632,\"memory\":71.7},{\"round\":2,\"log\":557,\"cpu\":4.955733999609947,\"memory\":77.29},{\"round\":2,\"log\":558,\"cpu\":0.20601899921894073,\"memory\":77.46},{\"round\":2,\"log\":559,\"cpu\":6.503895999863744,\"memory\":70.82},{\"round\":2,\"log\":560,\"cpu\":0.20496900007128716,\"memory\":70.95},{\"round\":2,\"log\":561,\"cpu\":6.551387000828981,\"memory\":77.83},{\"round\":2,\"log\":562,\"cpu\":0.08784900046885014,\"memory\":77.88},{\"round\":2,\"log\":563,\"cpu\":6.054049000144005,\"memory\":71.6},{\"round\":2,\"log\":564,\"cpu\":0.1488689985126257,\"memory\":71.76},{\"round\":2,\"log\":565,\"cpu\":5.018454000353813,\"memory\":77.43},{\"round\":2,\"log\":566,\"cpu\":0.2656280007213354,\"memory\":77.74},{\"round\":2,\"log\":567,\"cpu\":6.642276000231504,\"memory\":71.52},{\"round\":2,\"log\":568,\"cpu\":0.18732899986207485,\"memory\":71.65},{\"round\":2,\"log\":569,\"cpu\":6.5229159984737635,\"memory\":78.52},{\"round\":2,\"log\":570,\"cpu\":0.08107900060713291,\"memory\":78.58},{\"round\":2,\"log\":571,\"cpu\":6.042439000681043,\"memory\":71.94},{\"round\":2,\"log\":572,\"cpu\":0.1515589989721775,\"memory\":72.1},{\"round\":2,\"log\":573,\"cpu\":5.090444000437856,\"memory\":77.78},{\"round\":2,\"log\":574,\"cpu\":0.2596090007573366,\"memory\":78.09},{\"round\":2,\"log\":575,\"cpu\":6.606665000319481,\"memory\":71.7},{\"round\":2,\"log\":576,\"cpu\":6.567605998367071,\"memory\":75.25},{\"round\":2,\"log\":577,\"cpu\":6.71938499994576,\"memory\":78.82},{\"round\":2,\"log\":578,\"cpu\":0.22048900090157986,\"memory\":78.96},{\"round\":2,\"log\":579,\"cpu\":0.21374900080263615,\"memory\":79.09},{\"round\":2,\"log\":580,\"cpu\":0.21245899982750416,\"memory\":79.23},{\"round\":2,\"log\":581,\"cpu\":0.21437899954617023,\"memory\":79.38},{\"round\":2,\"log\":582,\"cpu\":0.19286900013685226,\"memory\":79.51},{\"round\":2,\"log\":583,\"cpu\":121.18586099892855,\"memory\":116.16},{\"round\":2,\"log\":584,\"cpu\":0.05614900030195713,\"memory\":116.16},{\"round\":2,\"log\":585,\"cpu\":46.802108000963926,\"memory\":122.34},{\"round\":2,\"log\":586,\"cpu\":0.05605899915099144,\"memory\":122.34},{\"round\":2,\"log\":587,\"cpu\":3.782701000571251,\"memory\":125.13},{\"round\":2,\"log\":588,\"cpu\":8.338027000427246,\"memory\":124.58},{\"round\":2,\"log\":589,\"cpu\":1.3613229990005493,\"memory\":125.7},{\"round\":2,\"log\":590,\"cpu\":2.7498950008302927,\"memory\":128.73},{\"round\":2,\"log\":591,\"cpu\":0.646696999669075,\"memory\":129.29},{\"round\":2,\"log\":592,\"cpu\":3.8959100004285574,\"memory\":133.38},{\"round\":2,\"log\":593,\"cpu\":0.9537149984389544,\"memory\":134.15},{\"round\":2,\"log\":594,\"cpu\":2.545677000656724,\"memory\":121.52},{\"round\":2,\"log\":595,\"cpu\":6.15586700104177,\"memory\":127.96},{\"round\":2,\"log\":596,\"cpu\":1.359612999483943,\"memory\":129.08},{\"round\":2,\"log\":597,\"cpu\":2.5587769988924265,\"memory\":132.09},{\"round\":2,\"log\":598,\"cpu\":0.6039370000362396,\"memory\":132.66},{\"round\":2,\"log\":599,\"cpu\":4.523207001388073,\"memory\":122.49},{\"round\":2,\"log\":600,\"cpu\":0.9176249988377094,\"memory\":123.26},{\"round\":2,\"log\":601,\"cpu\":1.7712510004639626,\"memory\":125.31},{\"round\":2,\"log\":602,\"cpu\":0.398887999355793,\"memory\":125.7},{\"round\":2,\"log\":603,\"cpu\":4.947794001549482,\"memory\":131.73},{\"round\":2,\"log\":604,\"cpu\":1.6372609995305538,\"memory\":133.4},{\"round\":2,\"log\":605,\"cpu\":4.911225000396371,\"memory\":125.34},{\"round\":2,\"log\":606,\"cpu\":0.7241259999573231,\"memory\":126.09},{\"round\":2,\"log\":607,\"cpu\":4.138528998941183,\"memory\":130.79},{\"round\":2,\"log\":608,\"cpu\":1.3189129997044802,\"memory\":132},{\"round\":2,\"log\":609,\"cpu\":2.8788350000977516,\"memory\":134.85},{\"round\":2,\"log\":610,\"cpu\":0.6684659998863935,\"memory\":135.38},{\"round\":2,\"log\":611,\"cpu\":6.0977389998734,\"memory\":127.14},{\"round\":2,\"log\":612,\"cpu\":2.0108490008860826,\"memory\":128.9},{\"round\":2,\"log\":613,\"cpu\":4.037838999181986,\"memory\":133.08},{\"round\":2,\"log\":614,\"cpu\":0.8074060007929802,\"memory\":133.91},{\"round\":2,\"log\":615,\"cpu\":5.294592000544071,\"memory\":124.91},{\"round\":2,\"log\":616,\"cpu\":1.3653229996562004,\"memory\":126.16},{\"round\":2,\"log\":617,\"cpu\":2.5950269997119904,\"memory\":129.02},{\"round\":2,\"log\":618,\"cpu\":0.6031870003789663,\"memory\":129.6},{\"round\":2,\"log\":619,\"cpu\":6.722504999488592,\"memory\":124.03},{\"round\":2,\"log\":620,\"cpu\":0.10406900011003017,\"memory\":124.1},{\"round\":2,\"log\":621,\"cpu\":3.7270509991794825,\"memory\":128.21},{\"round\":2,\"log\":622,\"cpu\":0.05059000104665756,\"memory\":128.23},{\"round\":2,\"log\":623,\"cpu\":4.458426998928189,\"memory\":132.91},{\"round\":2,\"log\":624,\"cpu\":0.09971900098025799,\"memory\":132.95},{\"round\":2,\"log\":625,\"cpu\":3.498692000284791,\"memory\":122.84},{\"round\":2,\"log\":626,\"cpu\":0.055010000243783,\"memory\":122.86},{\"round\":2,\"log\":627,\"cpu\":5.638910999521613,\"memory\":129.29},{\"round\":2,\"log\":628,\"cpu\":0.1328389998525381,\"memory\":129.38},{\"round\":2,\"log\":629,\"cpu\":3.782700000330806,\"memory\":133.47},{\"round\":2,\"log\":630,\"cpu\":0.09479000046849251,\"memory\":133.51},{\"round\":2,\"log\":631,\"cpu\":5.043783999979496,\"memory\":124.57},{\"round\":2,\"log\":632,\"cpu\":0.135428998619318,\"memory\":124.64},{\"round\":2,\"log\":633,\"cpu\":2.5285370014607906,\"memory\":127.41},{\"round\":2,\"log\":634,\"cpu\":0.07632899843156338,\"memory\":127.45},{\"round\":2,\"log\":635,\"cpu\":5.726781001314521,\"memory\":133.86},{\"round\":2,\"log\":636,\"cpu\":0.22041899897158146,\"memory\":134.03},{\"round\":2,\"log\":637,\"cpu\":5.100812999531627,\"memory\":125.18},{\"round\":2,\"log\":638,\"cpu\":0.12375900149345398,\"memory\":125.27},{\"round\":2,\"log\":639,\"cpu\":3.9810699988156557,\"memory\":129.88},{\"round\":2,\"log\":640,\"cpu\":0.17819900065660477,\"memory\":130.01},{\"round\":2,\"log\":641,\"cpu\":2.632915999740362,\"memory\":132.74},{\"round\":2,\"log\":642,\"cpu\":0.11058999970555305,\"memory\":132.8},{\"round\":2,\"log\":643,\"cpu\":6.233447000384331,\"memory\":125.58},{\"round\":2,\"log\":644,\"cpu\":0.40251800045371056,\"memory\":125.9},{\"round\":2,\"log\":645,\"cpu\":3.470812000334263,\"memory\":129.77},{\"round\":2,\"log\":646,\"cpu\":0.21172899939119816,\"memory\":129.93},{\"round\":2,\"log\":647,\"cpu\":4.404337000101805,\"memory\":134.48},{\"round\":2,\"log\":648,\"cpu\":0.3104880005121231,\"memory\":134.71},{\"round\":2,\"log\":649,\"cpu\":3.502371998503804,\"memory\":123.25},{\"round\":2,\"log\":650,\"cpu\":0.17155900038778782,\"memory\":123.36},{\"round\":2,\"log\":651,\"cpu\":5.253433000296354,\"memory\":129.7},{\"round\":2,\"log\":652,\"cpu\":0.04852000065147877,\"memory\":129.72},{\"round\":2,\"log\":653,\"cpu\":3.8094499986618757,\"memory\":133.87},{\"round\":2,\"log\":654,\"cpu\":0.03953000158071518,\"memory\":133.88},{\"round\":2,\"log\":655,\"cpu\":5.013303998857737,\"memory\":124.85},{\"round\":2,\"log\":656,\"cpu\":0.061560001224279404,\"memory\":124.88},{\"round\":2,\"log\":657,\"cpu\":2.5497059989720583,\"memory\":127.7},{\"round\":2,\"log\":658,\"cpu\":0.033479999750852585,\"memory\":127.71},{\"round\":2,\"log\":659,\"cpu\":5.747181000187993,\"memory\":134.14},{\"round\":2,\"log\":660,\"cpu\":0.08734899945557117,\"memory\":134.17},{\"round\":2,\"log\":661,\"cpu\":5.332702001556754,\"memory\":125.7},{\"round\":2,\"log\":662,\"cpu\":0.04546999931335449,\"memory\":125.71},{\"round\":2,\"log\":663,\"cpu\":4.036648999899626,\"memory\":130.4},{\"round\":2,\"log\":664,\"cpu\":0.05229000002145767,\"memory\":130.42},{\"round\":2,\"log\":665,\"cpu\":2.8197150006890297,\"memory\":133.25},{\"round\":2,\"log\":666,\"cpu\":0.039959998801350594,\"memory\":133.26},{\"round\":2,\"log\":667,\"cpu\":6.361657001078129,\"memory\":125.89},{\"round\":2,\"log\":668,\"cpu\":0.07626999914646149,\"memory\":125.93},{\"round\":2,\"log\":669,\"cpu\":3.864070000126958,\"memory\":130.08},{\"round\":2,\"log\":670,\"cpu\":0.05169899947941303,\"memory\":130.11},{\"round\":2,\"log\":671,\"cpu\":4.545456001535058,\"memory\":134.8},{\"round\":2,\"log\":672,\"cpu\":0.07053999975323677,\"memory\":134.84},{\"round\":2,\"log\":673,\"cpu\":3.973879998549819,\"memory\":123.93},{\"round\":2,\"log\":674,\"cpu\":0.04987900145351887,\"memory\":123.95},{\"round\":2,\"log\":675,\"cpu\":5.327842999249697,\"memory\":130.38},{\"round\":2,\"log\":676,\"cpu\":0.10230899974703789,\"memory\":130.46},{\"round\":2,\"log\":677,\"cpu\":3.840099999681115,\"memory\":134.61},{\"round\":2,\"log\":678,\"cpu\":0.06823999993503094,\"memory\":134.64},{\"round\":2,\"log\":679,\"cpu\":5.032634001225233,\"memory\":125.32},{\"round\":2,\"log\":680,\"cpu\":0.09765899926424026,\"memory\":125.39},{\"round\":2,\"log\":681,\"cpu\":2.528226999565959,\"memory\":128.21},{\"round\":2,\"log\":682,\"cpu\":0.059220001101493835,\"memory\":128.24},{\"round\":2,\"log\":683,\"cpu\":4.552885999903083,\"memory\":131.18},{\"round\":2,\"log\":684,\"cpu\":0.1868089996278286,\"memory\":131.26},{\"round\":2,\"log\":685,\"cpu\":0.18067900091409683,\"memory\":131.34},{\"round\":2,\"log\":686,\"cpu\":0.2758089993149042,\"memory\":131.48},{\"round\":2,\"log\":687,\"cpu\":0.26550900004804134,\"memory\":131.62},{\"round\":2,\"log\":688,\"cpu\":0.5020369999110699,\"memory\":131.88},{\"round\":2,\"log\":689,\"cpu\":0.4573279991745949,\"memory\":132.13},{\"round\":2,\"log\":690,\"cpu\":0.9270550012588501,\"memory\":132.65},{\"round\":2,\"log\":691,\"cpu\":0.18823899887502193,\"memory\":132.77},{\"round\":2,\"log\":692,\"cpu\":5.959519000723958,\"memory\":124.46},{\"round\":2,\"log\":693,\"cpu\":1.8071110006421804,\"memory\":126.18},{\"round\":2,\"log\":694,\"cpu\":4.472675999626517,\"memory\":131.35},{\"round\":2,\"log\":695,\"cpu\":1.025824999436736,\"memory\":132.33},{\"round\":2,\"log\":696,\"cpu\":5.330142000690103,\"memory\":123.97},{\"round\":2,\"log\":697,\"cpu\":0.8496959991753101,\"memory\":124.84},{\"round\":2,\"log\":698,\"cpu\":4.083628000691533,\"memory\":129.64},{\"round\":2,\"log\":699,\"cpu\":0.7421669997274876,\"memory\":130.5},{\"round\":2,\"log\":700,\"cpu\":16.17718599922955,\"memory\":135.49},{\"round\":2,\"log\":701,\"cpu\":11.078843001276255,\"memory\":136.14},{\"round\":2,\"log\":702,\"cpu\":2.059348998591304,\"memory\":137.85},{\"round\":2,\"log\":703,\"cpu\":7.338721999898553,\"memory\":132.85},{\"round\":2,\"log\":704,\"cpu\":1.043714001774788,\"memory\":133.84},{\"round\":2,\"log\":705,\"cpu\":4.284237999469042,\"memory\":138.68},{\"round\":2,\"log\":706,\"cpu\":0.8619749993085861,\"memory\":139.55},{\"round\":2,\"log\":707,\"cpu\":5.047274000942707,\"memory\":130.95},{\"round\":2,\"log\":708,\"cpu\":0.9244359992444515,\"memory\":131.81},{\"round\":2,\"log\":709,\"cpu\":16.946751000359654,\"memory\":139.83},{\"round\":2,\"log\":710,\"cpu\":3.7124210000038147,\"memory\":142.6},{\"round\":2,\"log\":711,\"cpu\":5.505521999672055,\"memory\":132.77},{\"round\":2,\"log\":712,\"cpu\":6.8559140004217625,\"memory\":136.32},{\"round\":2,\"log\":713,\"cpu\":6.8423449993133545,\"memory\":143.2},{\"round\":2,\"log\":714,\"cpu\":2.9567140005528927,\"memory\":131.77},{\"round\":2,\"log\":715,\"cpu\":4.984414000064135,\"memory\":137.59},{\"round\":2,\"log\":716,\"cpu\":1.013204999268055,\"memory\":139},{\"round\":2,\"log\":717,\"cpu\":5.859780000522733,\"memory\":133.47},{\"round\":2,\"log\":718,\"cpu\":0.9039549995213747,\"memory\":134.7},{\"round\":2,\"log\":719,\"cpu\":6.003829000517726,\"memory\":140.72},{\"round\":2,\"log\":720,\"cpu\":0.11119900085031986,\"memory\":140.8},{\"round\":2,\"log\":721,\"cpu\":7.783409999683499,\"memory\":135.08},{\"round\":2,\"log\":722,\"cpu\":0.05443999916315079,\"memory\":135.1},{\"round\":2,\"log\":723,\"cpu\":5.1093029994517565,\"memory\":140.93},{\"round\":2,\"log\":724,\"cpu\":0.04327000118792057,\"memory\":140.94},{\"round\":2,\"log\":725,\"cpu\":5.8645089995115995,\"memory\":134.47},{\"round\":2,\"log\":726,\"cpu\":0.045779999345541,\"memory\":134.49},{\"round\":2,\"log\":727,\"cpu\":5.948419000953436,\"memory\":140.51},{\"round\":2,\"log\":728,\"cpu\":0.08964999951422215,\"memory\":140.59},{\"round\":2,\"log\":729,\"cpu\":7.158022999763489,\"memory\":135},{\"round\":2,\"log\":730,\"cpu\":0.0794489998370409,\"memory\":135.02},{\"round\":2,\"log\":731,\"cpu\":5.410711999982595,\"memory\":140.85},{\"round\":2,\"log\":732,\"cpu\":0.04535000026226044,\"memory\":140.86},{\"round\":2,\"log\":733,\"cpu\":5.577571000903845,\"memory\":134.43},{\"round\":2,\"log\":734,\"cpu\":0.044280000030994415,\"memory\":134.44},{\"round\":2,\"log\":735,\"cpu\":6.1008879989385605,\"memory\":140.46},{\"round\":2,\"log\":736,\"cpu\":0.09896999970078468,\"memory\":140.54},{\"round\":2,\"log\":737,\"cpu\":7.1198330000042915,\"memory\":134.96},{\"round\":2,\"log\":738,\"cpu\":0.06424900144338608,\"memory\":134.99},{\"round\":2,\"log\":739,\"cpu\":5.3435429986566305,\"memory\":140.8},{\"round\":2,\"log\":740,\"cpu\":0.10853900015354156,\"memory\":140.89},{\"round\":2,\"log\":741,\"cpu\":5.813380001112819,\"memory\":134.13},{\"round\":2,\"log\":742,\"cpu\":0.18436899967491627,\"memory\":134.31},{\"round\":2,\"log\":743,\"cpu\":5.744750000536442,\"memory\":140.15},{\"round\":2,\"log\":744,\"cpu\":0.10360999964177608,\"memory\":140.23},{\"round\":2,\"log\":745,\"cpu\":7.36519099958241,\"memory\":134.77},{\"round\":2,\"log\":746,\"cpu\":0.060750000178813934,\"memory\":134.8},{\"round\":2,\"log\":747,\"cpu\":5.201462998986244,\"memory\":140.6},{\"round\":2,\"log\":748,\"cpu\":0.10721900127828121,\"memory\":140.7},{\"round\":2,\"log\":749,\"cpu\":5.572700999677181,\"memory\":134.06},{\"round\":2,\"log\":750,\"cpu\":0.17745999991893768,\"memory\":134.23},{\"round\":2,\"log\":751,\"cpu\":5.882448999211192,\"memory\":140.08},{\"round\":2,\"log\":752,\"cpu\":0.1967690009623766,\"memory\":140.21},{\"round\":2,\"log\":753,\"cpu\":7.19450300000608,\"memory\":134.81},{\"round\":2,\"log\":754,\"cpu\":0.08816899918019772,\"memory\":134.86},{\"round\":2,\"log\":755,\"cpu\":5.068204000592232,\"memory\":140.69},{\"round\":2,\"log\":756,\"cpu\":0.1468889992684126,\"memory\":140.85},{\"round\":2,\"log\":757,\"cpu\":6.127899000421166,\"memory\":134.42},{\"round\":2,\"log\":758,\"cpu\":0.24670800007879734,\"memory\":134.73},{\"round\":2,\"log\":759,\"cpu\":5.9758790004998446,\"memory\":140.75},{\"round\":2,\"log\":760,\"cpu\":0.18231900036334991,\"memory\":140.88},{\"round\":2,\"log\":761,\"cpu\":7.106312999501824,\"memory\":135.12},{\"round\":2,\"log\":762,\"cpu\":0.08957000076770782,\"memory\":135.17},{\"round\":2,\"log\":763,\"cpu\":5.428031999617815,\"memory\":141},{\"round\":2,\"log\":764,\"cpu\":0.14547899924218655,\"memory\":141.16},{\"round\":2,\"log\":765,\"cpu\":5.728530000895262,\"memory\":134.59},{\"round\":2,\"log\":766,\"cpu\":0.25119899958372116,\"memory\":134.9},{\"round\":2,\"log\":767,\"cpu\":5.963289000093937,\"memory\":140.92},{\"round\":2,\"log\":768,\"cpu\":7.281001999974251,\"memory\":131.14},{\"round\":2,\"log\":769,\"cpu\":6.6939249988645315,\"memory\":134.7},{\"round\":2,\"log\":770,\"cpu\":0.2197790015488863,\"memory\":134.84},{\"round\":2,\"log\":771,\"cpu\":0.21484899893403053,\"memory\":134.97},{\"round\":2,\"log\":772,\"cpu\":0.2047290001064539,\"memory\":135.11},{\"round\":2,\"log\":773,\"cpu\":0.21181900054216385,\"memory\":135.26},{\"round\":2,\"log\":774,\"cpu\":0.1908390000462532,\"memory\":135.39},{\"round\":2,\"log\":775,\"cpu\":118.37724499963224,\"memory\":181.56},{\"round\":2,\"log\":776,\"cpu\":0.055570000782608986,\"memory\":181.56},{\"round\":2,\"log\":777,\"cpu\":46.700577998533845,\"memory\":188.28},{\"round\":2,\"log\":778,\"cpu\":0.05542000010609627,\"memory\":188.28},{\"round\":2,\"log\":779,\"cpu\":6.250687001273036,\"memory\":183.74},{\"round\":2,\"log\":780,\"cpu\":5.57753099873662,\"memory\":189.78},{\"round\":2,\"log\":781,\"cpu\":1.3012630008161068,\"memory\":190.9},{\"round\":2,\"log\":782,\"cpu\":2.932295000180602,\"memory\":193.92},{\"round\":2,\"log\":783,\"cpu\":0.6229570005089045,\"memory\":194.48},{\"round\":2,\"log\":784,\"cpu\":5.973258998245001,\"memory\":186.87},{\"round\":2,\"log\":785,\"cpu\":0.8851150013506413,\"memory\":187.64},{\"round\":2,\"log\":786,\"cpu\":2.030969999730587,\"memory\":189.69},{\"round\":2,\"log\":787,\"cpu\":6.06033799983561,\"memory\":196.12},{\"round\":2,\"log\":788,\"cpu\":1.2325040008872747,\"memory\":197.24},{\"round\":2,\"log\":789,\"cpu\":3.3046329990029335,\"memory\":185.27},{\"round\":2,\"log\":790,\"cpu\":0.76082600094378,\"memory\":185.83},{\"round\":2,\"log\":791,\"cpu\":3.6281709987670183,\"memory\":189.92},{\"round\":2,\"log\":792,\"cpu\":0.7977259997278452,\"memory\":190.69},{\"round\":2,\"log\":793,\"cpu\":1.7735210005193949,\"memory\":192.74},{\"round\":2,\"log\":794,\"cpu\":0.41448800079524517,\"memory\":193.13},{\"round\":2,\"log\":795,\"cpu\":5.911628998816013,\"memory\":186.04},{\"round\":2,\"log\":796,\"cpu\":1.7511609997600317,\"memory\":187.71},{\"round\":2,\"log\":797,\"cpu\":3.739460000768304,\"memory\":191.89},{\"round\":2,\"log\":798,\"cpu\":0.7264460008591413,\"memory\":192.64},{\"round\":2,\"log\":799,\"cpu\":4.2044889982789755,\"memory\":197.34},{\"round\":2,\"log\":800,\"cpu\":2.278948001563549,\"memory\":184.84},{\"round\":2,\"log\":801,\"cpu\":2.772954998537898,\"memory\":187.69},{\"round\":2,\"log\":802,\"cpu\":0.563017001375556,\"memory\":188.22},{\"round\":2,\"log\":803,\"cpu\":5.584041999652982,\"memory\":194.67},{\"round\":2,\"log\":804,\"cpu\":1.9784089997410774,\"memory\":196.42},{\"round\":2,\"log\":805,\"cpu\":5.1635829992592335,\"memory\":188.31},{\"round\":2,\"log\":806,\"cpu\":0.7891460005193949,\"memory\":189.15},{\"round\":2,\"log\":807,\"cpu\":4.161648999899626,\"memory\":193.84},{\"round\":2,\"log\":808,\"cpu\":1.5516320001333952,\"memory\":195.1},{\"round\":2,\"log\":809,\"cpu\":2.83763499930501,\"memory\":197.95},{\"round\":2,\"log\":810,\"cpu\":1.4469220004975796,\"memory\":183.84},{\"round\":2,\"log\":811,\"cpu\":5.6733909994363785,\"memory\":190.28},{\"round\":2,\"log\":812,\"cpu\":0.10566900111734867,\"memory\":190.35},{\"round\":2,\"log\":813,\"cpu\":3.958510000258684,\"memory\":194.46},{\"round\":2,\"log\":814,\"cpu\":0.05087999999523163,\"memory\":194.48},{\"round\":2,\"log\":815,\"cpu\":5.779169999063015,\"memory\":186.56},{\"round\":2,\"log\":816,\"cpu\":0.1053990013897419,\"memory\":186.61},{\"round\":2,\"log\":817,\"cpu\":2.6335569992661476,\"memory\":189.41},{\"round\":2,\"log\":818,\"cpu\":0.04694899916648865,\"memory\":189.43},{\"round\":2,\"log\":819,\"cpu\":5.333233000710607,\"memory\":195.85},{\"round\":2,\"log\":820,\"cpu\":0.14030900038778782,\"memory\":195.95},{\"round\":2,\"log\":821,\"cpu\":5.093082999810576,\"memory\":187.83},{\"round\":2,\"log\":822,\"cpu\":0.09855999983847141,\"memory\":187.88},{\"round\":2,\"log\":823,\"cpu\":4.186728000640869,\"memory\":192.54},{\"round\":2,\"log\":824,\"cpu\":0.140259999781847,\"memory\":192.61},{\"round\":2,\"log\":825,\"cpu\":2.7774249985814095,\"memory\":195.38},{\"round\":2,\"log\":826,\"cpu\":0.08106000162661076,\"memory\":195.42},{\"round\":2,\"log\":827,\"cpu\":6.964113999158144,\"memory\":188.39},{\"round\":2,\"log\":828,\"cpu\":0.22143799997866154,\"memory\":188.55},{\"round\":2,\"log\":829,\"cpu\":3.72410099953413,\"memory\":192.57},{\"round\":2,\"log\":830,\"cpu\":0.12863999977707863,\"memory\":192.66},{\"round\":2,\"log\":831,\"cpu\":4.383766001090407,\"memory\":197.28},{\"round\":2,\"log\":832,\"cpu\":0.1955289989709854,\"memory\":197.4},{\"round\":2,\"log\":833,\"cpu\":3.472163001075387,\"memory\":186.38},{\"round\":2,\"log\":834,\"cpu\":0.11541900038719177,\"memory\":186.44},{\"round\":2,\"log\":835,\"cpu\":5.345162998884916,\"memory\":192.83},{\"round\":2,\"log\":836,\"cpu\":0.38065800070762634,\"memory\":193.15},{\"round\":2,\"log\":837,\"cpu\":3.722029998898506,\"memory\":197.02},{\"round\":2,\"log\":838,\"cpu\":0.216219000518322,\"memory\":197.18},{\"round\":2,\"log\":839,\"cpu\":4.768525000661612,\"memory\":187.59},{\"round\":2,\"log\":840,\"cpu\":0.3429089989513159,\"memory\":187.82},{\"round\":2,\"log\":841,\"cpu\":2.383677000179887,\"memory\":190.44},{\"round\":2,\"log\":842,\"cpu\":0.15679899975657463,\"memory\":190.56},{\"round\":2,\"log\":843,\"cpu\":5.457272000610828,\"memory\":196.9},{\"round\":2,\"log\":844,\"cpu\":0.051009999588131905,\"memory\":196.92},{\"round\":2,\"log\":845,\"cpu\":4.8093539997935295,\"memory\":188.55},{\"round\":2,\"log\":846,\"cpu\":0.038670001551508904,\"memory\":188.57},{\"round\":2,\"log\":847,\"cpu\":4.075268998742104,\"memory\":193.25},{\"round\":2,\"log\":848,\"cpu\":0.046470001339912415,\"memory\":193.27},{\"round\":2,\"log\":849,\"cpu\":2.6653859987854958,\"memory\":196.1},{\"round\":2,\"log\":850,\"cpu\":0.03368000127375126,\"memory\":196.11},{\"round\":2,\"log\":851,\"cpu\":6.732904998585582,\"memory\":188.84},{\"round\":2,\"log\":852,\"cpu\":0.0603800006210804,\"memory\":188.87},{\"round\":2,\"log\":853,\"cpu\":3.868569999933243,\"memory\":193.02},{\"round\":2,\"log\":854,\"cpu\":0.03928999975323677,\"memory\":193.03},{\"round\":2,\"log\":855,\"cpu\":4.521705999970436,\"memory\":197.71},{\"round\":2,\"log\":856,\"cpu\":0.05319000035524368,\"memory\":197.74},{\"round\":2,\"log\":857,\"cpu\":4.358526999130845,\"memory\":186.86},{\"round\":2,\"log\":858,\"cpu\":0.04181000031530857,\"memory\":186.87},{\"round\":2,\"log\":859,\"cpu\":5.277123000472784,\"memory\":193.31},{\"round\":2,\"log\":860,\"cpu\":0.06892899982631207,\"memory\":193.35},{\"round\":2,\"log\":861,\"cpu\":3.8647399991750717,\"memory\":197.5},{\"round\":2,\"log\":862,\"cpu\":0.05170000158250332,\"memory\":197.52},{\"round\":2,\"log\":863,\"cpu\":5.113373998552561,\"memory\":188.2},{\"round\":2,\"log\":864,\"cpu\":0.0687790010124445,\"memory\":188.24},{\"round\":2,\"log\":865,\"cpu\":2.486616998910904,\"memory\":191.06},{\"round\":2,\"log\":866,\"cpu\":0.046300001442432404,\"memory\":191.08},{\"round\":2,\"log\":867,\"cpu\":5.835439998656511,\"memory\":197.51},{\"round\":2,\"log\":868,\"cpu\":0.11610900051891804,\"memory\":197.59},{\"round\":2,\"log\":869,\"cpu\":5.3143729995936155,\"memory\":188.99},{\"round\":2,\"log\":870,\"cpu\":0.06460900045931339,\"memory\":189.03},{\"round\":2,\"log\":871,\"cpu\":3.9914090000092983,\"memory\":193.71},{\"round\":2,\"log\":872,\"cpu\":0.0925500001758337,\"memory\":193.78},{\"round\":2,\"log\":873,\"cpu\":2.7905860003083944,\"memory\":196.6},{\"round\":2,\"log\":874,\"cpu\":0.06799899972975254,\"memory\":196.64},{\"round\":2,\"log\":875,\"cpu\":5.824929999187589,\"memory\":185.4},{\"round\":2,\"log\":876,\"cpu\":0.19055900163948536,\"memory\":185.48},{\"round\":2,\"log\":877,\"cpu\":0.1516689993441105,\"memory\":185.55},{\"round\":2,\"log\":878,\"cpu\":0.24814900010824203,\"memory\":185.69},{\"round\":2,\"log\":879,\"cpu\":0.29117799922823906,\"memory\":185.83},{\"round\":2,\"log\":880,\"cpu\":0.4442580007016659,\"memory\":186.09},{\"round\":2,\"log\":881,\"cpu\":0.44759799912571907,\"memory\":186.35},{\"round\":2,\"log\":882,\"cpu\":0.8704350013285875,\"memory\":186.87},{\"round\":2,\"log\":883,\"cpu\":0.19477899931371212,\"memory\":186.99},{\"round\":2,\"log\":884,\"cpu\":4.831605000421405,\"memory\":192.11},{\"round\":2,\"log\":885,\"cpu\":2.0357789993286133,\"memory\":193.83},{\"round\":2,\"log\":886,\"cpu\":6.13539900071919,\"memory\":186.46},{\"round\":2,\"log\":887,\"cpu\":1.0313839986920357,\"memory\":187.44},{\"round\":2,\"log\":888,\"cpu\":3.9053200017660856,\"memory\":192.28},{\"round\":2,\"log\":889,\"cpu\":0.7590259984135628,\"memory\":193.16},{\"round\":2,\"log\":890,\"cpu\":4.103449000045657,\"memory\":197.96},{\"round\":2,\"log\":891,\"cpu\":0.8029660005122423,\"memory\":198.82},{\"round\":2,\"log\":892,\"cpu\":18.04862600006163,\"memory\":193.5},{\"round\":2,\"log\":893,\"cpu\":11.963587999343872,\"memory\":194.74},{\"round\":2,\"log\":894,\"cpu\":2.061489000916481,\"memory\":196.46},{\"round\":2,\"log\":895,\"cpu\":4.695175999775529,\"memory\":201.62},{\"round\":2,\"log\":896,\"cpu\":0.92981499992311,\"memory\":202.6},{\"round\":2,\"log\":897,\"cpu\":5.3058129996061325,\"memory\":194.02},{\"round\":2,\"log\":898,\"cpu\":1.0236140005290508,\"memory\":194.9},{\"round\":2,\"log\":899,\"cpu\":4.374627999961376,\"memory\":199.7},{\"round\":2,\"log\":900,\"cpu\":0.7626660000532866,\"memory\":200.56},{\"round\":2,\"log\":901,\"cpu\":16.436455000191927,\"memory\":205.89},{\"round\":2,\"log\":902,\"cpu\":6.129208000376821,\"memory\":201.27},{\"round\":2,\"log\":903,\"cpu\":5.003203999251127,\"memory\":206.38},{\"round\":2,\"log\":904,\"cpu\":6.521546000614762,\"memory\":209.94},{\"round\":2,\"log\":905,\"cpu\":9.06063299998641,\"memory\":207.84},{\"round\":2,\"log\":906,\"cpu\":1.5402619987726212,\"memory\":209.6},{\"round\":2,\"log\":907,\"cpu\":6.565626000985503,\"memory\":204.36},{\"round\":2,\"log\":908,\"cpu\":1.1070440001785755,\"memory\":205.77},{\"round\":2,\"log\":909,\"cpu\":4.907174998894334,\"memory\":211.44},{\"round\":2,\"log\":910,\"cpu\":0.8786550015211105,\"memory\":212.67},{\"round\":2,\"log\":911,\"cpu\":6.885833999142051,\"memory\":205.98},{\"round\":2,\"log\":912,\"cpu\":0.11031999997794628,\"memory\":206.06},{\"round\":2,\"log\":913,\"cpu\":6.526165999472141,\"memory\":212.94},{\"round\":2,\"log\":914,\"cpu\":0.04983000084757805,\"memory\":212.96},{\"round\":2,\"log\":915,\"cpu\":6.174536999315023,\"memory\":206.05},{\"round\":2,\"log\":916,\"cpu\":0.047290001064538956,\"memory\":206.06},{\"round\":2,\"log\":917,\"cpu\":5.122344000265002,\"memory\":211.74},{\"round\":2,\"log\":918,\"cpu\":0.04212999902665615,\"memory\":211.75},{\"round\":2,\"log\":919,\"cpu\":6.596175000071526,\"memory\":205.4},{\"round\":2,\"log\":920,\"cpu\":0.09324000030755997,\"memory\":205.48},{\"round\":2,\"log\":921,\"cpu\":6.5641259998083115,\"memory\":212.36},{\"round\":2,\"log\":922,\"cpu\":0.04944000020623207,\"memory\":212.38},{\"round\":2,\"log\":923,\"cpu\":5.94887899979949,\"memory\":205.77},{\"round\":2,\"log\":924,\"cpu\":0.04507900029420853,\"memory\":205.79},{\"round\":2,\"log\":925,\"cpu\":4.934594999998808,\"memory\":211.47},{\"round\":2,\"log\":926,\"cpu\":0.040710000321269035,\"memory\":211.48},{\"round\":2,\"log\":927,\"cpu\":6.871923999860883,\"memory\":205.31},{\"round\":2,\"log\":928,\"cpu\":0.10635999962687492,\"memory\":205.39},{\"round\":2,\"log\":929,\"cpu\":6.528684999793768,\"memory\":212.26},{\"round\":2,\"log\":930,\"cpu\":0.06289000064134598,\"memory\":212.29},{\"round\":2,\"log\":931,\"cpu\":5.785799998790026,\"memory\":205.64},{\"round\":2,\"log\":932,\"cpu\":0.1136000007390976,\"memory\":205.73},{\"round\":2,\"log\":933,\"cpu\":4.928733998909593,\"memory\":211.31},{\"round\":2,\"log\":934,\"cpu\":0.1848290003836155,\"memory\":211.49},{\"round\":2,\"log\":935,\"cpu\":6.961554000154138,\"memory\":204.68},{\"round\":2,\"log\":936,\"cpu\":0.10751000046730042,\"memory\":204.76},{\"round\":2,\"log\":937,\"cpu\":6.5261160004884005,\"memory\":211.63},{\"round\":2,\"log\":938,\"cpu\":0.060808999463915825,\"memory\":211.66},{\"round\":2,\"log\":939,\"cpu\":6.006008999422193,\"memory\":205.31},{\"round\":2,\"log\":940,\"cpu\":0.11099000088870525,\"memory\":205.4},{\"round\":2,\"log\":941,\"cpu\":4.9100339990109205,\"memory\":210.99},{\"round\":2,\"log\":942,\"cpu\":0.19563900120556355,\"memory\":211.16},{\"round\":2,\"log\":943,\"cpu\":6.848964000120759,\"memory\":204.6},{\"round\":2,\"log\":944,\"cpu\":0.22036899998784065,\"memory\":204.72},{\"round\":2,\"log\":945,\"cpu\":6.567405998706818,\"memory\":211.6},{\"round\":2,\"log\":946,\"cpu\":0.08720000088214874,\"memory\":211.65},{\"round\":2,\"log\":947,\"cpu\":5.954028999432921,\"memory\":205.39},{\"round\":2,\"log\":948,\"cpu\":0.1465889997780323,\"memory\":205.55},{\"round\":2,\"log\":949,\"cpu\":5.078813999891281,\"memory\":211.23},{\"round\":2,\"log\":950,\"cpu\":0.2603489998728037,\"memory\":211.54},{\"round\":2,\"log\":951,\"cpu\":7.082533000037074,\"memory\":205.34},{\"round\":2,\"log\":952,\"cpu\":0.1885290015488863,\"memory\":205.47},{\"round\":2,\"log\":953,\"cpu\":6.574575999751687,\"memory\":212.34},{\"round\":2,\"log\":954,\"cpu\":0.07685899920761585,\"memory\":212.4},{\"round\":2,\"log\":955,\"cpu\":6.093848999589682,\"memory\":205.79},{\"round\":2,\"log\":956,\"cpu\":0.14735900051891804,\"memory\":205.95},{\"round\":2,\"log\":957,\"cpu\":4.9962339997291565,\"memory\":211.63},{\"round\":2,\"log\":958,\"cpu\":0.24728900007903576,\"memory\":211.94},{\"round\":2,\"log\":959,\"cpu\":6.553666001185775,\"memory\":205.56},{\"round\":2,\"log\":960,\"cpu\":6.740354999899864,\"memory\":209.11},{\"round\":2,\"log\":961,\"cpu\":6.694074999541044,\"memory\":212.67},{\"round\":2,\"log\":962,\"cpu\":0.21995900012552738,\"memory\":212.8},{\"round\":2,\"log\":963,\"cpu\":0.21366900019347668,\"memory\":212.94},{\"round\":2,\"log\":964,\"cpu\":0.20532899908721447,\"memory\":213.08},{\"round\":2,\"log\":965,\"cpu\":0.21287900023162365,\"memory\":213.23},{\"round\":2,\"log\":966,\"cpu\":0.19177900068461895,\"memory\":213.36},{\"round\":2,\"log\":967,\"cpu\":138.63049099966884,\"memory\":46.42},{\"round\":2,\"log\":968,\"cpu\":0.0658390000462532,\"memory\":46.42},{\"round\":2,\"log\":969,\"cpu\":46.150301000103354,\"memory\":53.19},{\"round\":2,\"log\":970,\"cpu\":0.05587000027298927,\"memory\":53.2}],[{\"round\":3,\"log\":0,\"cpu\":16.977272000163794,\"memory\":9.93},{\"round\":3,\"log\":1,\"cpu\":2.1905889995396137,\"memory\":11.23},{\"round\":3,\"log\":2,\"cpu\":0.13972900062799454,\"memory\":11.24},{\"round\":3,\"log\":3,\"cpu\":0.23535900004208088,\"memory\":11.27},{\"round\":3,\"log\":4,\"cpu\":0.11622899957001209,\"memory\":11.29},{\"round\":3,\"log\":5,\"cpu\":0.11336000077426434,\"memory\":11.3},{\"round\":3,\"log\":6,\"cpu\":0.05776899866759777,\"memory\":11.31},{\"round\":3,\"log\":7,\"cpu\":0.3814580012112856,\"memory\":11.47},{\"round\":3,\"log\":8,\"cpu\":0.13463000021874905,\"memory\":11.5},{\"round\":3,\"log\":9,\"cpu\":0.2577579990029335,\"memory\":11.57},{\"round\":3,\"log\":10,\"cpu\":0.11524000018835068,\"memory\":11.59},{\"round\":3,\"log\":11,\"cpu\":1.1506730001419783,\"memory\":13.04},{\"round\":3,\"log\":12,\"cpu\":10.902014000341296,\"memory\":6.64},{\"round\":3,\"log\":13,\"cpu\":1.629551999270916,\"memory\":7.76},{\"round\":3,\"log\":14,\"cpu\":4.362337000668049,\"memory\":10.95},{\"round\":3,\"log\":15,\"cpu\":0.7454860005527735,\"memory\":11.51},{\"round\":3,\"log\":16,\"cpu\":5.19408299960196,\"memory\":15.68},{\"round\":3,\"log\":17,\"cpu\":2.2520779985934496,\"memory\":4.17},{\"round\":3,\"log\":18,\"cpu\":2.4473280012607574,\"memory\":6.25},{\"round\":3,\"log\":19,\"cpu\":7.604569999501109,\"memory\":12.82},{\"round\":3,\"log\":20,\"cpu\":1.4275930002331734,\"memory\":13.94},{\"round\":3,\"log\":21,\"cpu\":3.582991000264883,\"memory\":17.01},{\"round\":3,\"log\":22,\"cpu\":1.359222998842597,\"memory\":3.42},{\"round\":3,\"log\":23,\"cpu\":4.514485999941826,\"memory\":7.55},{\"round\":3,\"log\":24,\"cpu\":0.9837050009518862,\"memory\":8.34},{\"round\":3,\"log\":25,\"cpu\":2.253158999606967,\"memory\":10.41},{\"round\":3,\"log\":26,\"cpu\":0.4730370007455349,\"memory\":10.8},{\"round\":3,\"log\":27,\"cpu\":6.268897999078035,\"memory\":16.91},{\"round\":3,\"log\":28,\"cpu\":3.066304000094533,\"memory\":5.9},{\"round\":3,\"log\":29,\"cpu\":4.4981869999319315,\"memory\":10.17},{\"round\":3,\"log\":30,\"cpu\":0.8396260011941195,\"memory\":10.93},{\"round\":3,\"log\":31,\"cpu\":5.173901999369264,\"memory\":15.72},{\"round\":3,\"log\":32,\"cpu\":1.702531998977065,\"memory\":16.94},{\"round\":3,\"log\":33,\"cpu\":3.8695500008761883,\"memory\":6.13},{\"round\":3,\"log\":34,\"cpu\":0.6790260002017021,\"memory\":6.68},{\"round\":3,\"log\":35,\"cpu\":6.9343039989471436,\"memory\":13.34},{\"round\":3,\"log\":36,\"cpu\":2.385538000613451,\"memory\":15.19},{\"round\":3,\"log\":37,\"cpu\":5.125753000378609,\"memory\":7.24},{\"round\":3,\"log\":38,\"cpu\":0.8957950007170439,\"memory\":8.08},{\"round\":3,\"log\":39,\"cpu\":4.598766999319196,\"memory\":12.76},{\"round\":3,\"log\":40,\"cpu\":1.5742220003157854,\"memory\":14.02},{\"round\":3,\"log\":41,\"cpu\":2.8922849986702204,\"memory\":16.88},{\"round\":3,\"log\":42,\"cpu\":0.7086460012942553,\"memory\":17.47},{\"round\":3,\"log\":43,\"cpu\":6.476425999775529,\"memory\":9.28},{\"round\":3,\"log\":44,\"cpu\":0.13834000006318092,\"memory\":9.34},{\"round\":3,\"log\":45,\"cpu\":4.311506999656558,\"memory\":13.46},{\"round\":3,\"log\":46,\"cpu\":0.059700001031160355,\"memory\":13.48},{\"round\":3,\"log\":47,\"cpu\":5.432311998680234,\"memory\":5.63},{\"round\":3,\"log\":48,\"cpu\":0.11916900053620338,\"memory\":5.68},{\"round\":3,\"log\":49,\"cpu\":2.783704999834299,\"memory\":8.48},{\"round\":3,\"log\":50,\"cpu\":0.05100000090897083,\"memory\":8.5},{\"round\":3,\"log\":51,\"cpu\":5.704450998455286,\"memory\":14.95},{\"round\":3,\"log\":52,\"cpu\":0.1718589998781681,\"memory\":15.05},{\"round\":3,\"log\":53,\"cpu\":5.089403999969363,\"memory\":6.95},{\"round\":3,\"log\":54,\"cpu\":0.10242900066077709,\"memory\":7},{\"round\":3,\"log\":55,\"cpu\":4.412306999787688,\"memory\":11.63},{\"round\":3,\"log\":56,\"cpu\":0.1513190008699894,\"memory\":11.71},{\"round\":3,\"log\":57,\"cpu\":2.877794999629259,\"memory\":14.49},{\"round\":3,\"log\":58,\"cpu\":0.0865700002759695,\"memory\":14.53},{\"round\":3,\"log\":59,\"cpu\":6.760514998808503,\"memory\":7.56},{\"round\":3,\"log\":60,\"cpu\":0.26024800166487694,\"memory\":7.73},{\"round\":3,\"log\":61,\"cpu\":3.974049998447299,\"memory\":11.74},{\"round\":3,\"log\":62,\"cpu\":0.13919899985194206,\"memory\":11.82},{\"round\":3,\"log\":63,\"cpu\":4.560826001688838,\"memory\":16.42},{\"round\":3,\"log\":64,\"cpu\":0.21048899926245213,\"memory\":16.54},{\"round\":3,\"log\":65,\"cpu\":3.7177709992974997,\"memory\":5.54},{\"round\":3,\"log\":66,\"cpu\":0.1230590008199215,\"memory\":5.61},{\"round\":3,\"log\":67,\"cpu\":5.556021999567747,\"memory\":12.03},{\"round\":3,\"log\":68,\"cpu\":0.4068080000579357,\"memory\":12.34},{\"round\":3,\"log\":69,\"cpu\":3.7882199995219707,\"memory\":16.21},{\"round\":3,\"log\":70,\"cpu\":0.24215800128877163,\"memory\":16.36},{\"round\":3,\"log\":71,\"cpu\":4.925024999305606,\"memory\":6.74},{\"round\":3,\"log\":72,\"cpu\":0.3330080006271601,\"memory\":6.97},{\"round\":3,\"log\":73,\"cpu\":2.455527998507023,\"memory\":9.61},{\"round\":3,\"log\":74,\"cpu\":0.16503900103271008,\"memory\":9.72},{\"round\":3,\"log\":75,\"cpu\":5.908809000626206,\"memory\":16.09},{\"round\":3,\"log\":76,\"cpu\":0.07879999838769436,\"memory\":16.11},{\"round\":3,\"log\":77,\"cpu\":4.896754000335932,\"memory\":7.73},{\"round\":3,\"log\":78,\"cpu\":0.04263000003993511,\"memory\":7.75},{\"round\":3,\"log\":79,\"cpu\":4.18732799962163,\"memory\":12.41},{\"round\":3,\"log\":80,\"cpu\":0.053140001371502876,\"memory\":12.43},{\"round\":3,\"log\":81,\"cpu\":2.819514999166131,\"memory\":15.26},{\"round\":3,\"log\":82,\"cpu\":0.04033000022172928,\"memory\":15.27},{\"round\":3,\"log\":83,\"cpu\":6.595386000350118,\"memory\":8.01},{\"round\":3,\"log\":84,\"cpu\":0.08201999962329865,\"memory\":8.04},{\"round\":3,\"log\":85,\"cpu\":4.006768999621272,\"memory\":12.19},{\"round\":3,\"log\":86,\"cpu\":0.04756000079214573,\"memory\":12.2},{\"round\":3,\"log\":87,\"cpu\":4.8052949998527765,\"memory\":16.9},{\"round\":3,\"log\":88,\"cpu\":0.06548899970948696,\"memory\":16.93},{\"round\":3,\"log\":89,\"cpu\":3.372173000127077,\"memory\":6.06},{\"round\":3,\"log\":90,\"cpu\":0.04704900085926056,\"memory\":6.08},{\"round\":3,\"log\":91,\"cpu\":5.468801999464631,\"memory\":12.54},{\"round\":3,\"log\":92,\"cpu\":0.08241000026464462,\"memory\":12.58},{\"round\":3,\"log\":93,\"cpu\":3.9572289995849133,\"memory\":16.73},{\"round\":3,\"log\":94,\"cpu\":0.05419999919831753,\"memory\":16.75},{\"round\":3,\"log\":95,\"cpu\":4.872334999963641,\"memory\":7.42},{\"round\":3,\"log\":96,\"cpu\":0.07703900150954723,\"memory\":7.46},{\"round\":3,\"log\":97,\"cpu\":2.5836669988930225,\"memory\":10.28},{\"round\":3,\"log\":98,\"cpu\":0.04941900074481964,\"memory\":10.3},{\"round\":3,\"log\":99,\"cpu\":5.954579999670386,\"memory\":16.77},{\"round\":3,\"log\":100,\"cpu\":0.12469900026917458,\"memory\":16.84},{\"round\":3,\"log\":101,\"cpu\":4.912484999746084,\"memory\":8.3},{\"round\":3,\"log\":102,\"cpu\":0.0694389995187521,\"memory\":8.33},{\"round\":3,\"log\":103,\"cpu\":4.125238999724388,\"memory\":12.99},{\"round\":3,\"log\":104,\"cpu\":0.10417900048196316,\"memory\":13.06},{\"round\":3,\"log\":105,\"cpu\":2.750366000458598,\"memory\":15.88},{\"round\":3,\"log\":106,\"cpu\":0.07079999893903732,\"memory\":15.92},{\"round\":3,\"log\":107,\"cpu\":5.52683100104332,\"memory\":4.74},{\"round\":3,\"log\":108,\"cpu\":0.2016489990055561,\"memory\":4.81},{\"round\":3,\"log\":109,\"cpu\":0.1498390007764101,\"memory\":4.89},{\"round\":3,\"log\":110,\"cpu\":0.237678999081254,\"memory\":5.03},{\"round\":3,\"log\":111,\"cpu\":0.22644800134003162,\"memory\":5.17},{\"round\":3,\"log\":112,\"cpu\":0.43196799978613853,\"memory\":5.43},{\"round\":3,\"log\":113,\"cpu\":0.4112879987806082,\"memory\":5.68},{\"round\":3,\"log\":114,\"cpu\":0.8275360018014908,\"memory\":6.2},{\"round\":3,\"log\":115,\"cpu\":0.18616899847984314,\"memory\":6.32},{\"round\":3,\"log\":116,\"cpu\":5.234763000160456,\"memory\":11.46},{\"round\":3,\"log\":117,\"cpu\":2.088509000837803,\"memory\":13.18},{\"round\":3,\"log\":118,\"cpu\":6.039388999342918,\"memory\":5.79},{\"round\":3,\"log\":119,\"cpu\":1.0309549998492002,\"memory\":6.77},{\"round\":3,\"log\":120,\"cpu\":4.159978000447154,\"memory\":11.63},{\"round\":3,\"log\":121,\"cpu\":0.7675160001963377,\"memory\":12.51},{\"round\":3,\"log\":122,\"cpu\":4.313356999307871,\"memory\":17.33},{\"round\":3,\"log\":123,\"cpu\":0.8353160005062819,\"memory\":18.19},{\"round\":3,\"log\":124,\"cpu\":19.371009999886155,\"memory\":12.93},{\"round\":3,\"log\":125,\"cpu\":12.100796999409795,\"memory\":14.22},{\"round\":3,\"log\":126,\"cpu\":2.1233290005475283,\"memory\":15.94},{\"round\":3,\"log\":127,\"cpu\":4.824094999581575,\"memory\":21.09},{\"round\":3,\"log\":128,\"cpu\":1.0051550008356571,\"memory\":22.08},{\"round\":3,\"log\":129,\"cpu\":5.43304199911654,\"memory\":13.51},{\"round\":3,\"log\":130,\"cpu\":0.9864039998501539,\"memory\":14.38},{\"round\":3,\"log\":131,\"cpu\":4.536567000672221,\"memory\":19.19},{\"round\":3,\"log\":132,\"cpu\":0.8051050007343292,\"memory\":20.05},{\"round\":3,\"log\":133,\"cpu\":17.19718199968338,\"memory\":25.32},{\"round\":3,\"log\":134,\"cpu\":5.352580999955535,\"memory\":20.7},{\"round\":3,\"log\":135,\"cpu\":5.251124000176787,\"memory\":25.81},{\"round\":3,\"log\":136,\"cpu\":7.0706829987466335,\"memory\":29.45},{\"round\":3,\"log\":137,\"cpu\":8.917744001373649,\"memory\":27.42},{\"round\":3,\"log\":138,\"cpu\":1.7203909996896982,\"memory\":29.19},{\"round\":3,\"log\":139,\"cpu\":6.6505650002509356,\"memory\":23.81},{\"round\":3,\"log\":140,\"cpu\":1.1133340001106262,\"memory\":25.22},{\"round\":3,\"log\":141,\"cpu\":4.952394999563694,\"memory\":30.89},{\"round\":3,\"log\":142,\"cpu\":0.8793349992483854,\"memory\":32.13},{\"round\":3,\"log\":143,\"cpu\":6.980614000931382,\"memory\":25.37},{\"round\":3,\"log\":144,\"cpu\":0.11325899884104729,\"memory\":25.46},{\"round\":3,\"log\":145,\"cpu\":6.584426000714302,\"memory\":32.34},{\"round\":3,\"log\":146,\"cpu\":0.050119999796152115,\"memory\":32.36},{\"round\":3,\"log\":147,\"cpu\":6.037078000605106,\"memory\":25.5},{\"round\":3,\"log\":148,\"cpu\":0.046049999073147774,\"memory\":25.51},{\"round\":3,\"log\":149,\"cpu\":5.179934000596404,\"memory\":31.19},{\"round\":3,\"log\":150,\"cpu\":0.04217899963259697,\"memory\":31.2},{\"round\":3,\"log\":151,\"cpu\":7.014204001054168,\"memory\":24.84},{\"round\":3,\"log\":152,\"cpu\":0.09685899876058102,\"memory\":24.93},{\"round\":3,\"log\":153,\"cpu\":6.659486001357436,\"memory\":31.81},{\"round\":3,\"log\":154,\"cpu\":0.04715999960899353,\"memory\":31.83},{\"round\":3,\"log\":155,\"cpu\":6.405376000329852,\"memory\":25.19},{\"round\":3,\"log\":156,\"cpu\":0.04454999975860119,\"memory\":25.2},{\"round\":3,\"log\":157,\"cpu\":5.02891399897635,\"memory\":30.88},{\"round\":3,\"log\":158,\"cpu\":0.04065000079572201,\"memory\":30.89},{\"round\":3,\"log\":159,\"cpu\":6.904983999207616,\"memory\":24.66},{\"round\":3,\"log\":160,\"cpu\":0.09470999985933304,\"memory\":24.74},{\"round\":3,\"log\":161,\"cpu\":6.7190250009298325,\"memory\":31.61},{\"round\":3,\"log\":162,\"cpu\":0.06020999886095524,\"memory\":31.64},{\"round\":3,\"log\":163,\"cpu\":5.9180490002036095,\"memory\":25.02},{\"round\":3,\"log\":164,\"cpu\":0.11199900135397911,\"memory\":25.11},{\"round\":3,\"log\":165,\"cpu\":5.059053998440504,\"memory\":30.7},{\"round\":3,\"log\":166,\"cpu\":0.18632900156080723,\"memory\":30.87},{\"round\":3,\"log\":167,\"cpu\":6.906223999336362,\"memory\":24.07},{\"round\":3,\"log\":168,\"cpu\":0.11731000058352947,\"memory\":24.15},{\"round\":3,\"log\":169,\"cpu\":6.60423499904573,\"memory\":31.02},{\"round\":3,\"log\":170,\"cpu\":0.05774000100791454,\"memory\":31.05},{\"round\":3,\"log\":171,\"cpu\":6.018518999218941,\"memory\":24.72},{\"round\":3,\"log\":172,\"cpu\":0.1090290006250143,\"memory\":24.82},{\"round\":3,\"log\":173,\"cpu\":4.831594999879599,\"memory\":30.4},{\"round\":3,\"log\":174,\"cpu\":0.19239899888634682,\"memory\":30.58},{\"round\":3,\"log\":175,\"cpu\":6.769404999911785,\"memory\":23.96},{\"round\":3,\"log\":176,\"cpu\":0.22034900076687336,\"memory\":24.09},{\"round\":3,\"log\":177,\"cpu\":6.7561949994415045,\"memory\":30.96},{\"round\":3,\"log\":178,\"cpu\":0.083169000223279,\"memory\":31.02},{\"round\":3,\"log\":179,\"cpu\":6.065679000690579,\"memory\":24.73},{\"round\":3,\"log\":180,\"cpu\":0.14838000014424324,\"memory\":24.89},{\"round\":3,\"log\":181,\"cpu\":4.994192998856306,\"memory\":30.56},{\"round\":3,\"log\":182,\"cpu\":0.2644090000540018,\"memory\":30.87},{\"round\":3,\"log\":183,\"cpu\":6.996814001351595,\"memory\":24.69},{\"round\":3,\"log\":184,\"cpu\":0.1868089996278286,\"memory\":24.82},{\"round\":3,\"log\":185,\"cpu\":6.724785000085831,\"memory\":31.7},{\"round\":3,\"log\":186,\"cpu\":0.07850999943912029,\"memory\":31.75},{\"round\":3,\"log\":187,\"cpu\":6.046258000656962,\"memory\":25.11},{\"round\":3,\"log\":188,\"cpu\":0.14729899913072586,\"memory\":25.27},{\"round\":3,\"log\":189,\"cpu\":5.213423000648618,\"memory\":30.94},{\"round\":3,\"log\":190,\"cpu\":0.25192900002002716,\"memory\":31.25},{\"round\":3,\"log\":191,\"cpu\":6.691205000504851,\"memory\":24.87},{\"round\":3,\"log\":192,\"cpu\":7.259112998843193,\"memory\":28.51},{\"round\":3,\"log\":193,\"cpu\":6.9946030005812645,\"memory\":32.1},{\"round\":3,\"log\":194,\"cpu\":0.22768899984657764,\"memory\":32.23},{\"round\":3,\"log\":195,\"cpu\":0.21851900033652782,\"memory\":32.37},{\"round\":3,\"log\":196,\"cpu\":0.21274899877607822,\"memory\":32.51},{\"round\":3,\"log\":197,\"cpu\":0.22269900143146515,\"memory\":32.66},{\"round\":3,\"log\":198,\"cpu\":0.19345899857580662,\"memory\":32.79},{\"round\":3,\"log\":199,\"cpu\":119.94421800039709,\"memory\":69.54},{\"round\":3,\"log\":200,\"cpu\":0.05347000062465668,\"memory\":69.54},{\"round\":3,\"log\":201,\"cpu\":47.787321999669075,\"memory\":75.75},{\"round\":3,\"log\":202,\"cpu\":0.05312900058925152,\"memory\":75.75},{\"round\":3,\"log\":203,\"cpu\":3.8390410002321005,\"memory\":78.53},{\"round\":3,\"log\":204,\"cpu\":8.160136999562383,\"memory\":78.01},{\"round\":3,\"log\":205,\"cpu\":1.4235929995775223,\"memory\":79.13},{\"round\":3,\"log\":206,\"cpu\":2.800976000726223,\"memory\":82.15},{\"round\":3,\"log\":207,\"cpu\":0.6532259993255138,\"memory\":82.72},{\"round\":3,\"log\":208,\"cpu\":3.9766700007021427,\"memory\":86.8},{\"round\":3,\"log\":209,\"cpu\":0.9240549989044666,\"memory\":87.58},{\"round\":3,\"log\":210,\"cpu\":2.6521860007196665,\"memory\":74.96},{\"round\":3,\"log\":211,\"cpu\":6.273248000070453,\"memory\":81.42},{\"round\":3,\"log\":212,\"cpu\":1.3696829993277788,\"memory\":82.54},{\"round\":3,\"log\":213,\"cpu\":2.632496001198888,\"memory\":85.56},{\"round\":3,\"log\":214,\"cpu\":0.5895569995045662,\"memory\":86.12},{\"round\":3,\"log\":215,\"cpu\":4.510056000202894,\"memory\":75.82},{\"round\":3,\"log\":216,\"cpu\":0.8874960001558065,\"memory\":76.59},{\"round\":3,\"log\":217,\"cpu\":1.8022909983992577,\"memory\":78.63},{\"round\":3,\"log\":218,\"cpu\":0.4080469999462366,\"memory\":79.02},{\"round\":3,\"log\":219,\"cpu\":5.090294001623988,\"memory\":85.05},{\"round\":3,\"log\":220,\"cpu\":1.721220999956131,\"memory\":86.76},{\"round\":3,\"log\":221,\"cpu\":4.985913999378681,\"memory\":78.6},{\"round\":3,\"log\":222,\"cpu\":0.725016999989748,\"memory\":79.35},{\"round\":3,\"log\":223,\"cpu\":4.14015799947083,\"memory\":84.02},{\"round\":3,\"log\":224,\"cpu\":1.293682999908924,\"memory\":85.2},{\"round\":3,\"log\":225,\"cpu\":2.8503160011023283,\"memory\":88.05},{\"round\":3,\"log\":226,\"cpu\":0.6442360002547503,\"memory\":88.58},{\"round\":3,\"log\":227,\"cpu\":6.182117998600006,\"memory\":80.35},{\"round\":3,\"log\":228,\"cpu\":2.077879000455141,\"memory\":82.12},{\"round\":3,\"log\":229,\"cpu\":4.109278999269009,\"memory\":86.3},{\"round\":3,\"log\":230,\"cpu\":0.7978560011833906,\"memory\":87.12},{\"round\":3,\"log\":231,\"cpu\":5.215872999280691,\"memory\":78.13},{\"round\":3,\"log\":232,\"cpu\":1.3968519996851683,\"memory\":79.37},{\"round\":3,\"log\":233,\"cpu\":2.65722700022161,\"memory\":82.22},{\"round\":3,\"log\":234,\"cpu\":0.6080569997429848,\"memory\":82.81},{\"round\":3,\"log\":235,\"cpu\":7.082983000203967,\"memory\":77.3},{\"round\":3,\"log\":236,\"cpu\":0.12135899998247623,\"memory\":77.36},{\"round\":3,\"log\":237,\"cpu\":3.7889210004359484,\"memory\":81.47},{\"round\":3,\"log\":238,\"cpu\":0.05021899938583374,\"memory\":81.49},{\"round\":3,\"log\":239,\"cpu\":4.488027000799775,\"memory\":86.14},{\"round\":3,\"log\":240,\"cpu\":0.10668900050222874,\"memory\":86.18},{\"round\":3,\"log\":241,\"cpu\":3.7698409985750914,\"memory\":76.12},{\"round\":3,\"log\":242,\"cpu\":0.05536000058054924,\"memory\":76.13},{\"round\":3,\"log\":243,\"cpu\":5.922298999503255,\"memory\":82.59},{\"round\":3,\"log\":244,\"cpu\":0.1570490002632141,\"memory\":82.68},{\"round\":3,\"log\":245,\"cpu\":4.137939000502229,\"memory\":86.76},{\"round\":3,\"log\":246,\"cpu\":0.10058899968862534,\"memory\":86.8},{\"round\":3,\"log\":247,\"cpu\":5.294683000072837,\"memory\":77.81},{\"round\":3,\"log\":248,\"cpu\":0.14139899984002113,\"memory\":77.88},{\"round\":3,\"log\":249,\"cpu\":2.6162160001695156,\"memory\":80.66},{\"round\":3,\"log\":250,\"cpu\":0.07699999958276749,\"memory\":80.7},{\"round\":3,\"log\":251,\"cpu\":5.921949001029134,\"memory\":87.13},{\"round\":3,\"log\":252,\"cpu\":0.25809899903833866,\"memory\":87.3},{\"round\":3,\"log\":253,\"cpu\":5.101094000041485,\"memory\":78.42},{\"round\":3,\"log\":254,\"cpu\":0.13719900138676167,\"memory\":78.5},{\"round\":3,\"log\":255,\"cpu\":4.0886689983308315,\"memory\":83.1},{\"round\":3,\"log\":256,\"cpu\":0.18688900023698807,\"memory\":83.22},{\"round\":3,\"log\":257,\"cpu\":2.8301750011742115,\"memory\":85.95},{\"round\":3,\"log\":258,\"cpu\":0.11565900035202503,\"memory\":86.01},{\"round\":3,\"log\":259,\"cpu\":6.458736998960376,\"memory\":78.79},{\"round\":3,\"log\":260,\"cpu\":0.4191980008035898,\"memory\":79.11},{\"round\":3,\"log\":261,\"cpu\":3.6430309992283583,\"memory\":82.97},{\"round\":3,\"log\":262,\"cpu\":0.2200790010392666,\"memory\":83.12},{\"round\":3,\"log\":263,\"cpu\":4.414986999705434,\"memory\":87.68},{\"round\":3,\"log\":264,\"cpu\":0.3258179984986782,\"memory\":87.91},{\"round\":3,\"log\":265,\"cpu\":3.0993840005248785,\"memory\":76.55},{\"round\":3,\"log\":266,\"cpu\":0.17415899969637394,\"memory\":76.67},{\"round\":3,\"log\":267,\"cpu\":5.501881999894977,\"memory\":83.03},{\"round\":3,\"log\":268,\"cpu\":0.05120000056922436,\"memory\":83.06},{\"round\":3,\"log\":269,\"cpu\":3.968869000673294,\"memory\":87.2},{\"round\":3,\"log\":270,\"cpu\":0.0353389997035265,\"memory\":87.21},{\"round\":3,\"log\":271,\"cpu\":5.157603999599814,\"memory\":78.19},{\"round\":3,\"log\":272,\"cpu\":0.04828999936580658,\"memory\":78.21},{\"round\":3,\"log\":273,\"cpu\":2.599506000056863,\"memory\":81.04},{\"round\":3,\"log\":274,\"cpu\":0.033810000866651535,\"memory\":81.05},{\"round\":3,\"log\":275,\"cpu\":5.731659999117255,\"memory\":87.51},{\"round\":3,\"log\":276,\"cpu\":0.05593000166118145,\"memory\":87.54},{\"round\":3,\"log\":277,\"cpu\":5.483401998877525,\"memory\":79.04},{\"round\":3,\"log\":278,\"cpu\":0.04243900068104267,\"memory\":79.06},{\"round\":3,\"log\":279,\"cpu\":4.086949000135064,\"memory\":83.72},{\"round\":3,\"log\":280,\"cpu\":0.054250000044703484,\"memory\":83.75},{\"round\":3,\"log\":281,\"cpu\":2.8894250001758337,\"memory\":86.57},{\"round\":3,\"log\":282,\"cpu\":0.042419999837875366,\"memory\":86.58},{\"round\":3,\"log\":283,\"cpu\":6.303416999056935,\"memory\":79.22},{\"round\":3,\"log\":284,\"cpu\":0.07658899948000908,\"memory\":79.27},{\"round\":3,\"log\":285,\"cpu\":3.898980000987649,\"memory\":83.41},{\"round\":3,\"log\":286,\"cpu\":0.052470000460743904,\"memory\":83.43},{\"round\":3,\"log\":287,\"cpu\":4.578776000067592,\"memory\":88.09},{\"round\":3,\"log\":288,\"cpu\":0.07223000004887581,\"memory\":88.13},{\"round\":3,\"log\":289,\"cpu\":3.4450619984418154,\"memory\":77.26},{\"round\":3,\"log\":290,\"cpu\":0.049720000475645065,\"memory\":77.28},{\"round\":3,\"log\":291,\"cpu\":5.433242000639439,\"memory\":83.74},{\"round\":3,\"log\":292,\"cpu\":0.10942899994552135,\"memory\":83.81},{\"round\":3,\"log\":293,\"cpu\":3.9521599989384413,\"memory\":87.96},{\"round\":3,\"log\":294,\"cpu\":0.07053900137543678,\"memory\":87.99},{\"round\":3,\"log\":295,\"cpu\":5.085163999348879,\"memory\":78.58},{\"round\":3,\"log\":296,\"cpu\":0.10640900023281574,\"memory\":78.65},{\"round\":3,\"log\":297,\"cpu\":2.566516999155283,\"memory\":81.47},{\"round\":3,\"log\":298,\"cpu\":0.06307000108063221,\"memory\":81.51},{\"round\":3,\"log\":299,\"cpu\":4.301117999479175,\"memory\":84.45},{\"round\":3,\"log\":300,\"cpu\":0.1757689993828535,\"memory\":84.53},{\"round\":3,\"log\":301,\"cpu\":0.14360900036990643,\"memory\":84.6},{\"round\":3,\"log\":302,\"cpu\":0.25117900036275387,\"memory\":84.74},{\"round\":3,\"log\":303,\"cpu\":0.2340879999101162,\"memory\":84.88},{\"round\":3,\"log\":304,\"cpu\":0.4374679997563362,\"memory\":85.13},{\"round\":3,\"log\":305,\"cpu\":0.41027799993753433,\"memory\":85.39},{\"round\":3,\"log\":306,\"cpu\":0.8788350000977516,\"memory\":85.91},{\"round\":3,\"log\":307,\"cpu\":0.2421090006828308,\"memory\":86.03},{\"round\":3,\"log\":308,\"cpu\":5.872299998998642,\"memory\":77.73},{\"round\":3,\"log\":309,\"cpu\":1.8316300008445978,\"memory\":79.45},{\"round\":3,\"log\":310,\"cpu\":4.348496999591589,\"memory\":84.61},{\"round\":3,\"log\":311,\"cpu\":0.912576001137495,\"memory\":85.59},{\"round\":3,\"log\":312,\"cpu\":5.33071199990809,\"memory\":77.21},{\"round\":3,\"log\":313,\"cpu\":0.8394459988921881,\"memory\":78.09},{\"round\":3,\"log\":314,\"cpu\":4.0837590005248785,\"memory\":82.89},{\"round\":3,\"log\":315,\"cpu\":0.7425260003656149,\"memory\":83.75},{\"round\":3,\"log\":316,\"cpu\":16.57494399882853,\"memory\":88.73},{\"round\":3,\"log\":317,\"cpu\":11.188582001253963,\"memory\":89.39},{\"round\":3,\"log\":318,\"cpu\":2.043188998475671,\"memory\":91.1},{\"round\":3,\"log\":319,\"cpu\":6.653266001492739,\"memory\":86.1},{\"round\":3,\"log\":320,\"cpu\":1.0690039992332458,\"memory\":87.08},{\"round\":3,\"log\":321,\"cpu\":4.548275999724865,\"memory\":91.92},{\"round\":3,\"log\":322,\"cpu\":0.9527550004422665,\"memory\":92.79},{\"round\":3,\"log\":323,\"cpu\":5.2016940005123615,\"memory\":84.27},{\"round\":3,\"log\":324,\"cpu\":0.9496449995785952,\"memory\":85.13},{\"round\":3,\"log\":325,\"cpu\":16.880052000284195,\"memory\":93.17},{\"round\":3,\"log\":326,\"cpu\":3.7452210001647472,\"memory\":95.94},{\"round\":3,\"log\":327,\"cpu\":5.603380998596549,\"memory\":86.06},{\"round\":3,\"log\":328,\"cpu\":6.751775000244379,\"memory\":89.63},{\"round\":3,\"log\":329,\"cpu\":6.8505640011280775,\"memory\":96.5},{\"round\":3,\"log\":330,\"cpu\":2.4310170002281666,\"memory\":85.06},{\"round\":3,\"log\":331,\"cpu\":4.954814998432994,\"memory\":90.89},{\"round\":3,\"log\":332,\"cpu\":1.0346450004726648,\"memory\":92.3},{\"round\":3,\"log\":333,\"cpu\":5.970327999442816,\"memory\":86.74},{\"round\":3,\"log\":334,\"cpu\":0.9139960017055273,\"memory\":87.97},{\"round\":3,\"log\":335,\"cpu\":6.028558999300003,\"memory\":93.99},{\"round\":3,\"log\":336,\"cpu\":0.09932900033891201,\"memory\":94.07},{\"round\":3,\"log\":337,\"cpu\":7.504820998758078,\"memory\":88.34},{\"round\":3,\"log\":338,\"cpu\":0.05278000049293041,\"memory\":88.36},{\"round\":3,\"log\":339,\"cpu\":5.173413001000881,\"memory\":94.19},{\"round\":3,\"log\":340,\"cpu\":0.041259998455643654,\"memory\":94.2},{\"round\":3,\"log\":341,\"cpu\":5.674620000645518,\"memory\":87.73},{\"round\":3,\"log\":342,\"cpu\":0.04319999925792217,\"memory\":87.74},{\"round\":3,\"log\":343,\"cpu\":6.04890900105238,\"memory\":93.76},{\"round\":3,\"log\":344,\"cpu\":0.08908900059759617,\"memory\":93.85},{\"round\":3,\"log\":345,\"cpu\":7.129323998466134,\"memory\":88.35},{\"round\":3,\"log\":346,\"cpu\":0.048789000138640404,\"memory\":88.37},{\"round\":3,\"log\":347,\"cpu\":5.193432999774814,\"memory\":94.2},{\"round\":3,\"log\":348,\"cpu\":0.04130000062286854,\"memory\":94.21},{\"round\":3,\"log\":349,\"cpu\":5.620811000466347,\"memory\":87.8},{\"round\":3,\"log\":350,\"cpu\":0.042819999158382416,\"memory\":87.81},{\"round\":3,\"log\":351,\"cpu\":6.083228001371026,\"memory\":93.83},{\"round\":3,\"log\":352,\"cpu\":0.09147999994456768,\"memory\":93.91},{\"round\":3,\"log\":353,\"cpu\":7.122562998905778,\"memory\":88.34},{\"round\":3,\"log\":354,\"cpu\":0.08146900124847889,\"memory\":88.37},{\"round\":3,\"log\":355,\"cpu\":5.112723998725414,\"memory\":94.18},{\"round\":3,\"log\":356,\"cpu\":0.10490900091826916,\"memory\":94.27},{\"round\":3,\"log\":357,\"cpu\":5.642191000282764,\"memory\":87.57},{\"round\":3,\"log\":358,\"cpu\":0.18762899935245514,\"memory\":87.74},{\"round\":3,\"log\":359,\"cpu\":5.736269999295473,\"memory\":93.59},{\"round\":3,\"log\":360,\"cpu\":0.0956800002604723,\"memory\":93.67},{\"round\":3,\"log\":361,\"cpu\":7.2125630006194115,\"memory\":88.2},{\"round\":3,\"log\":362,\"cpu\":0.062439000234007835,\"memory\":88.23},{\"round\":3,\"log\":363,\"cpu\":5.211622999981046,\"memory\":94.03},{\"round\":3,\"log\":364,\"cpu\":0.11802900023758411,\"memory\":94.12},{\"round\":3,\"log\":365,\"cpu\":5.477841999381781,\"memory\":87.49},{\"round\":3,\"log\":366,\"cpu\":0.17657900042831898,\"memory\":87.67},{\"round\":3,\"log\":367,\"cpu\":6.088247999548912,\"memory\":93.52},{\"round\":3,\"log\":368,\"cpu\":0.2041190005838871,\"memory\":93.65},{\"round\":3,\"log\":369,\"cpu\":7.1731529999524355,\"memory\":88.19},{\"round\":3,\"log\":370,\"cpu\":0.08576999977231026,\"memory\":88.24},{\"round\":3,\"log\":371,\"cpu\":5.252072999253869,\"memory\":94.07},{\"round\":3,\"log\":372,\"cpu\":0.1425090003758669,\"memory\":94.23},{\"round\":3,\"log\":373,\"cpu\":6.323687000200152,\"memory\":87.77},{\"round\":3,\"log\":374,\"cpu\":0.25302799977362156,\"memory\":88.08},{\"round\":3,\"log\":375,\"cpu\":6.085309000685811,\"memory\":94.1},{\"round\":3,\"log\":376,\"cpu\":0.17790899984538555,\"memory\":94.23},{\"round\":3,\"log\":377,\"cpu\":7.209253000095487,\"memory\":88.52},{\"round\":3,\"log\":378,\"cpu\":0.08438899926841259,\"memory\":88.57},{\"round\":3,\"log\":379,\"cpu\":5.422632999718189,\"memory\":94.39},{\"round\":3,\"log\":380,\"cpu\":0.14553900063037872,\"memory\":94.55},{\"round\":3,\"log\":381,\"cpu\":5.69717999920249,\"memory\":87.96},{\"round\":3,\"log\":382,\"cpu\":0.2502990011125803,\"memory\":88.27},{\"round\":3,\"log\":383,\"cpu\":6.261567998677492,\"memory\":94.28},{\"round\":3,\"log\":384,\"cpu\":7.1482720002532005,\"memory\":84.48},{\"round\":3,\"log\":385,\"cpu\":6.7435750011354685,\"memory\":88.04},{\"round\":3,\"log\":386,\"cpu\":0.22007899917662144,\"memory\":88.17},{\"round\":3,\"log\":387,\"cpu\":0.2155189998447895,\"memory\":88.31},{\"round\":3,\"log\":388,\"cpu\":0.207719000056386,\"memory\":88.45},{\"round\":3,\"log\":389,\"cpu\":0.21293899975717068,\"memory\":88.59},{\"round\":3,\"log\":390,\"cpu\":0.1906989999115467,\"memory\":88.73},{\"round\":3,\"log\":391,\"cpu\":134.7054019998759,\"memory\":42.94},{\"round\":3,\"log\":392,\"cpu\":0.05996900051832199,\"memory\":42.94},{\"round\":3,\"log\":393,\"cpu\":43.65414400026202,\"memory\":55.96},{\"round\":3,\"log\":394,\"cpu\":0.05478000082075596,\"memory\":55.97},{\"round\":3,\"log\":395,\"cpu\":6.2029079999774694,\"memory\":51.62},{\"round\":3,\"log\":396,\"cpu\":5.758909998461604,\"memory\":57.67},{\"round\":3,\"log\":397,\"cpu\":3.0117640011012554,\"memory\":51.48},{\"round\":3,\"log\":398,\"cpu\":2.8860449995845556,\"memory\":54.5},{\"round\":3,\"log\":399,\"cpu\":0.5909669995307922,\"memory\":55.06},{\"round\":3,\"log\":400,\"cpu\":3.891550000756979,\"memory\":59.15},{\"round\":3,\"log\":401,\"cpu\":0.9475749991834164,\"memory\":59.92},{\"round\":3,\"log\":402,\"cpu\":1.9736599996685982,\"memory\":61.97},{\"round\":3,\"log\":403,\"cpu\":6.929634001106024,\"memory\":54.6},{\"round\":3,\"log\":404,\"cpu\":1.2750829998403788,\"memory\":55.72},{\"round\":3,\"log\":405,\"cpu\":2.7386060003191233,\"memory\":58.74},{\"round\":3,\"log\":406,\"cpu\":0.6528270002454519,\"memory\":59.3},{\"round\":3,\"log\":407,\"cpu\":3.8752699997276068,\"memory\":63.39},{\"round\":3,\"log\":408,\"cpu\":1.4612920004874468,\"memory\":50.46},{\"round\":3,\"log\":409,\"cpu\":1.8301199991255999,\"memory\":52.51},{\"round\":3,\"log\":410,\"cpu\":0.4135079998522997,\"memory\":52.89},{\"round\":3,\"log\":411,\"cpu\":5.115283999592066,\"memory\":58.93},{\"round\":3,\"log\":412,\"cpu\":1.8590400014072657,\"memory\":60.63},{\"round\":3,\"log\":413,\"cpu\":5.57604099996388,\"memory\":53.22},{\"round\":3,\"log\":414,\"cpu\":0.9043359998613596,\"memory\":53.97},{\"round\":3,\"log\":415,\"cpu\":4.19679799862206,\"memory\":58.64},{\"round\":3,\"log\":416,\"cpu\":1.3086430002003908,\"memory\":59.83},{\"round\":3,\"log\":417,\"cpu\":2.9751150012016296,\"memory\":62.67},{\"round\":3,\"log\":418,\"cpu\":0.6472169999033213,\"memory\":63.2},{\"round\":3,\"log\":419,\"cpu\":6.276466999202967,\"memory\":55.27},{\"round\":3,\"log\":420,\"cpu\":2.0680490005761385,\"memory\":57.04},{\"round\":3,\"log\":421,\"cpu\":3.9864600002765656,\"memory\":61.22},{\"round\":3,\"log\":422,\"cpu\":0.8302849996834993,\"memory\":62.04},{\"round\":3,\"log\":423,\"cpu\":5.349872000515461,\"memory\":53.23},{\"round\":3,\"log\":424,\"cpu\":1.385572999715805,\"memory\":54.47},{\"round\":3,\"log\":425,\"cpu\":2.637516999617219,\"memory\":57.32},{\"round\":3,\"log\":426,\"cpu\":0.6092370003461838,\"memory\":57.91},{\"round\":3,\"log\":427,\"cpu\":6.728744998574257,\"memory\":52.47},{\"round\":3,\"log\":428,\"cpu\":0.11663900129497051,\"memory\":52.52},{\"round\":3,\"log\":429,\"cpu\":3.751300999894738,\"memory\":56.63},{\"round\":3,\"log\":430,\"cpu\":0.048628998920321465,\"memory\":56.65},{\"round\":3,\"log\":431,\"cpu\":4.512117000296712,\"memory\":61.3},{\"round\":3,\"log\":432,\"cpu\":0.09597000107169151,\"memory\":61.35},{\"round\":3,\"log\":433,\"cpu\":4.120867999270558,\"memory\":51.31},{\"round\":3,\"log\":434,\"cpu\":0.06729999929666519,\"memory\":51.33},{\"round\":3,\"log\":435,\"cpu\":5.6615110002458096,\"memory\":57.79},{\"round\":3,\"log\":436,\"cpu\":0.14934900030493736,\"memory\":57.88},{\"round\":3,\"log\":437,\"cpu\":3.889589000493288,\"memory\":61.96},{\"round\":3,\"log\":438,\"cpu\":0.09022000059485435,\"memory\":62.01},{\"round\":3,\"log\":439,\"cpu\":5.095453999936581,\"memory\":53.13},{\"round\":3,\"log\":440,\"cpu\":0.13670899905264378,\"memory\":53.2},{\"round\":3,\"log\":441,\"cpu\":2.5437369998544455,\"memory\":55.98},{\"round\":3,\"log\":442,\"cpu\":0.07448999956250191,\"memory\":56.02},{\"round\":3,\"log\":443,\"cpu\":5.90828900039196,\"memory\":62.46},{\"round\":3,\"log\":444,\"cpu\":0.22820799984037876,\"memory\":62.62},{\"round\":3,\"log\":445,\"cpu\":5.287513000890613,\"memory\":53.79},{\"round\":3,\"log\":446,\"cpu\":0.1339999996125698,\"memory\":53.88},{\"round\":3,\"log\":447,\"cpu\":3.9695790000259876,\"memory\":58.47},{\"round\":3,\"log\":448,\"cpu\":0.18628899939358234,\"memory\":58.59},{\"round\":3,\"log\":449,\"cpu\":2.693376000970602,\"memory\":61.32},{\"round\":3,\"log\":450,\"cpu\":0.11270899884402752,\"memory\":61.38},{\"round\":3,\"log\":451,\"cpu\":6.312948001548648,\"memory\":54.13},{\"round\":3,\"log\":452,\"cpu\":0.40481799840927124,\"memory\":54.45},{\"round\":3,\"log\":453,\"cpu\":3.523351000621915,\"memory\":58.31},{\"round\":3,\"log\":454,\"cpu\":0.2205790001899004,\"memory\":58.46},{\"round\":3,\"log\":455,\"cpu\":4.458177000284195,\"memory\":62.99},{\"round\":3,\"log\":456,\"cpu\":0.31532800011336803,\"memory\":63.22},{\"round\":3,\"log\":457,\"cpu\":3.4345229994505644,\"memory\":51.79},{\"round\":3,\"log\":458,\"cpu\":0.1649590004235506,\"memory\":51.9},{\"round\":3,\"log\":459,\"cpu\":5.341811999678612,\"memory\":58.27},{\"round\":3,\"log\":460,\"cpu\":0.058730000630021095,\"memory\":58.29},{\"round\":3,\"log\":461,\"cpu\":3.83062999881804,\"memory\":62.44},{\"round\":3,\"log\":462,\"cpu\":0.038520000874996185,\"memory\":62.45},{\"round\":3,\"log\":463,\"cpu\":5.314182000234723,\"memory\":53.43},{\"round\":3,\"log\":464,\"cpu\":0.049869999289512634,\"memory\":53.45},{\"round\":3,\"log\":465,\"cpu\":2.570686999708414,\"memory\":56.27},{\"round\":3,\"log\":466,\"cpu\":0.03324900008738041,\"memory\":56.28},{\"round\":3,\"log\":467,\"cpu\":5.813571000471711,\"memory\":62.74},{\"round\":3,\"log\":468,\"cpu\":0.06005899980664253,\"memory\":62.77},{\"round\":3,\"log\":469,\"cpu\":5.143102999776602,\"memory\":54.29},{\"round\":3,\"log\":470,\"cpu\":0.04343000054359436,\"memory\":54.31},{\"round\":3,\"log\":471,\"cpu\":4.055348999798298,\"memory\":58.97},{\"round\":3,\"log\":472,\"cpu\":0.052400000393390656,\"memory\":59},{\"round\":3,\"log\":473,\"cpu\":2.86837499961257,\"memory\":61.82},{\"round\":3,\"log\":474,\"cpu\":0.03968000039458275,\"memory\":61.84},{\"round\":3,\"log\":475,\"cpu\":6.300007000565529,\"memory\":54.48},{\"round\":3,\"log\":476,\"cpu\":0.07756999880075455,\"memory\":54.53},{\"round\":3,\"log\":477,\"cpu\":3.855460001155734,\"memory\":58.67},{\"round\":3,\"log\":478,\"cpu\":0.07425899989902973,\"memory\":58.69},{\"round\":3,\"log\":479,\"cpu\":4.611685998737812,\"memory\":63.35},{\"round\":3,\"log\":480,\"cpu\":0.07231000065803528,\"memory\":63.39},{\"round\":3,\"log\":481,\"cpu\":3.8198000006377697,\"memory\":52.56},{\"round\":3,\"log\":482,\"cpu\":0.049069998785853386,\"memory\":52.58},{\"round\":3,\"log\":483,\"cpu\":5.454532001167536,\"memory\":59.04},{\"round\":3,\"log\":484,\"cpu\":0.10443899966776371,\"memory\":59.12},{\"round\":3,\"log\":485,\"cpu\":3.911949999630451,\"memory\":63.26},{\"round\":3,\"log\":486,\"cpu\":0.06877899914979935,\"memory\":63.3},{\"round\":3,\"log\":487,\"cpu\":5.5149320010095835,\"memory\":53.9},{\"round\":3,\"log\":488,\"cpu\":0.1001800000667572,\"memory\":53.97},{\"round\":3,\"log\":489,\"cpu\":2.522555999457836,\"memory\":56.79},{\"round\":3,\"log\":490,\"cpu\":0.05911000072956085,\"memory\":56.82},{\"round\":3,\"log\":491,\"cpu\":4.485297000035644,\"memory\":59.77},{\"round\":3,\"log\":492,\"cpu\":0.20092899911105633,\"memory\":59.85},{\"round\":3,\"log\":493,\"cpu\":0.15603899955749512,\"memory\":59.92},{\"round\":3,\"log\":494,\"cpu\":0.25682900100946426,\"memory\":60.06},{\"round\":3,\"log\":495,\"cpu\":0.25570799969136715,\"memory\":60.2},{\"round\":3,\"log\":496,\"cpu\":0.46084799990057945,\"memory\":60.46},{\"round\":3,\"log\":497,\"cpu\":0.44256800040602684,\"memory\":60.71},{\"round\":3,\"log\":498,\"cpu\":0.9116249997168779,\"memory\":61.23},{\"round\":3,\"log\":499,\"cpu\":0.20961900055408478,\"memory\":61.35},{\"round\":3,\"log\":500,\"cpu\":6.040539000183344,\"memory\":53.09},{\"round\":3,\"log\":501,\"cpu\":1.8584300000220537,\"memory\":54.81},{\"round\":3,\"log\":502,\"cpu\":4.354466998949647,\"memory\":59.98},{\"round\":3,\"log\":503,\"cpu\":1.061514999717474,\"memory\":60.96},{\"round\":3,\"log\":504,\"cpu\":5.213163001462817,\"memory\":52.6},{\"round\":3,\"log\":505,\"cpu\":0.8266150001436472,\"memory\":53.48},{\"round\":3,\"log\":506,\"cpu\":3.9896299988031387,\"memory\":58.29},{\"round\":3,\"log\":507,\"cpu\":0.7294960003346205,\"memory\":59.15},{\"round\":3,\"log\":508,\"cpu\":16.770863000303507,\"memory\":64.15},{\"round\":3,\"log\":509,\"cpu\":11.012352999299765,\"memory\":64.82},{\"round\":3,\"log\":510,\"cpu\":2.0841390006244183,\"memory\":66.54},{\"round\":3,\"log\":511,\"cpu\":6.163278000429273,\"memory\":61.52},{\"round\":3,\"log\":512,\"cpu\":1.0839749984443188,\"memory\":62.51},{\"round\":3,\"log\":513,\"cpu\":4.361007001250982,\"memory\":67.35},{\"round\":3,\"log\":514,\"cpu\":0.9333950001746416,\"memory\":68.22},{\"round\":3,\"log\":515,\"cpu\":5.23611299879849,\"memory\":59.63},{\"round\":3,\"log\":516,\"cpu\":0.9140659999102354,\"memory\":60.49},{\"round\":3,\"log\":517,\"cpu\":16.71819300018251,\"memory\":68.53},{\"round\":3,\"log\":518,\"cpu\":3.700219999998808,\"memory\":71.3},{\"round\":3,\"log\":519,\"cpu\":5.828911000862718,\"memory\":61.46},{\"round\":3,\"log\":520,\"cpu\":6.938842998817563,\"memory\":65.03},{\"round\":3,\"log\":521,\"cpu\":6.761245001107454,\"memory\":71.91},{\"round\":3,\"log\":522,\"cpu\":2.4012679997831583,\"memory\":60.43},{\"round\":3,\"log\":523,\"cpu\":4.943274000659585,\"memory\":66.26},{\"round\":3,\"log\":524,\"cpu\":1.0109850000590086,\"memory\":67.67},{\"round\":3,\"log\":525,\"cpu\":6.216488000005484,\"memory\":62.11},{\"round\":3,\"log\":526,\"cpu\":0.9603849984705448,\"memory\":63.34},{\"round\":3,\"log\":527,\"cpu\":5.918039001524448,\"memory\":69.36},{\"round\":3,\"log\":528,\"cpu\":0.09957999922335148,\"memory\":69.44},{\"round\":3,\"log\":529,\"cpu\":7.391431000083685,\"memory\":63.75},{\"round\":3,\"log\":530,\"cpu\":0.05241999961435795,\"memory\":63.77},{\"round\":3,\"log\":531,\"cpu\":5.224983001127839,\"memory\":69.59},{\"round\":3,\"log\":532,\"cpu\":0.04285999946296215,\"memory\":69.61},{\"round\":3,\"log\":533,\"cpu\":5.744020000100136,\"memory\":63.09},{\"round\":3,\"log\":534,\"cpu\":0.04408000037074089,\"memory\":63.11},{\"round\":3,\"log\":535,\"cpu\":5.985248999670148,\"memory\":69.13},{\"round\":3,\"log\":536,\"cpu\":0.0883799996227026,\"memory\":69.21},{\"round\":3,\"log\":537,\"cpu\":7.067422999069095,\"memory\":63.66},{\"round\":3,\"log\":538,\"cpu\":0.04816900007426739,\"memory\":63.68},{\"round\":3,\"log\":539,\"cpu\":5.185124000534415,\"memory\":69.51},{\"round\":3,\"log\":540,\"cpu\":0.03969999961555004,\"memory\":69.52},{\"round\":3,\"log\":541,\"cpu\":5.650740001350641,\"memory\":63.07},{\"round\":3,\"log\":542,\"cpu\":0.04284000024199486,\"memory\":63.08},{\"round\":3,\"log\":543,\"cpu\":6.057178998365998,\"memory\":69.1},{\"round\":3,\"log\":544,\"cpu\":0.09001900069415569,\"memory\":69.18},{\"round\":3,\"log\":545,\"cpu\":7.271601999178529,\"memory\":63.62},{\"round\":3,\"log\":546,\"cpu\":0.06114000082015991,\"memory\":63.65},{\"round\":3,\"log\":547,\"cpu\":5.304253000766039,\"memory\":69.45},{\"round\":3,\"log\":548,\"cpu\":0.10793899931013584,\"memory\":69.54},{\"round\":3,\"log\":549,\"cpu\":5.6049610003829,\"memory\":62.78},{\"round\":3,\"log\":550,\"cpu\":0.17896899953484535,\"memory\":62.95},{\"round\":3,\"log\":551,\"cpu\":6.059799000620842,\"memory\":68.81},{\"round\":3,\"log\":552,\"cpu\":0.09789899922907352,\"memory\":68.89},{\"round\":3,\"log\":553,\"cpu\":7.3117820005863905,\"memory\":63.48},{\"round\":3,\"log\":554,\"cpu\":0.05975999869406223,\"memory\":63.51},{\"round\":3,\"log\":555,\"cpu\":5.188053000718355,\"memory\":69.32},{\"round\":3,\"log\":556,\"cpu\":0.11528000049293041,\"memory\":69.41},{\"round\":3,\"log\":557,\"cpu\":5.7270599994808435,\"memory\":62.75},{\"round\":3,\"log\":558,\"cpu\":0.17685900069773197,\"memory\":62.92},{\"round\":3,\"log\":559,\"cpu\":5.962798999622464,\"memory\":68.77},{\"round\":3,\"log\":560,\"cpu\":0.1934990007430315,\"memory\":68.9},{\"round\":3,\"log\":561,\"cpu\":7.0544029995799065,\"memory\":63.51},{\"round\":3,\"log\":562,\"cpu\":0.08840999938547611,\"memory\":63.56},{\"round\":3,\"log\":563,\"cpu\":5.274263000115752,\"memory\":69.39},{\"round\":3,\"log\":564,\"cpu\":0.14592899940907955,\"memory\":69.55},{\"round\":3,\"log\":565,\"cpu\":5.844020001590252,\"memory\":63.09},{\"round\":3,\"log\":566,\"cpu\":0.24479799903929234,\"memory\":63.4},{\"round\":3,\"log\":567,\"cpu\":6.080788999795914,\"memory\":69.42},{\"round\":3,\"log\":568,\"cpu\":0.17637900076806545,\"memory\":69.55},{\"round\":3,\"log\":569,\"cpu\":7.273582000285387,\"memory\":63.8},{\"round\":3,\"log\":570,\"cpu\":0.08469999954104424,\"memory\":63.85},{\"round\":3,\"log\":571,\"cpu\":5.350452000275254,\"memory\":69.68},{\"round\":3,\"log\":572,\"cpu\":0.1407689992338419,\"memory\":69.84},{\"round\":3,\"log\":573,\"cpu\":5.716850999742746,\"memory\":63.23},{\"round\":3,\"log\":574,\"cpu\":0.2504780013114214,\"memory\":63.54},{\"round\":3,\"log\":575,\"cpu\":6.076538998633623,\"memory\":69.56},{\"round\":3,\"log\":576,\"cpu\":7.4952310007065535,\"memory\":59.78},{\"round\":3,\"log\":577,\"cpu\":6.679324999451637,\"memory\":63.35},{\"round\":3,\"log\":578,\"cpu\":0.21438900008797646,\"memory\":63.48},{\"round\":3,\"log\":579,\"cpu\":0.207608999684453,\"memory\":63.62},{\"round\":3,\"log\":580,\"cpu\":0.20075900107622147,\"memory\":63.75},{\"round\":3,\"log\":581,\"cpu\":0.2079389989376068,\"memory\":63.9},{\"round\":3,\"log\":582,\"cpu\":0.18905900046229362,\"memory\":64.05},{\"round\":3,\"log\":583,\"cpu\":123.90783799998462,\"memory\":104.54},{\"round\":3,\"log\":584,\"cpu\":0.05165000073611736,\"memory\":104.54},{\"round\":3,\"log\":585,\"cpu\":44.30093999952078,\"memory\":117.58},{\"round\":3,\"log\":586,\"cpu\":0.05135999992489815,\"memory\":117.58},{\"round\":3,\"log\":587,\"cpu\":6.254057999700308,\"memory\":113.03},{\"round\":3,\"log\":588,\"cpu\":5.668750001117587,\"memory\":119.07},{\"round\":3,\"log\":589,\"cpu\":1.2708029989153147,\"memory\":120.19},{\"round\":3,\"log\":590,\"cpu\":3.065574999898672,\"memory\":123.21},{\"round\":3,\"log\":591,\"cpu\":2.6435759998857975,\"memory\":113.48},{\"round\":3,\"log\":592,\"cpu\":3.9685590006411076,\"memory\":117.57},{\"round\":3,\"log\":593,\"cpu\":0.861515998840332,\"memory\":118.34},{\"round\":3,\"log\":594,\"cpu\":1.8832400012761354,\"memory\":120.39},{\"round\":3,\"log\":595,\"cpu\":5.8145000003278255,\"memory\":126.85},{\"round\":3,\"log\":596,\"cpu\":2.2796179987490177,\"memory\":115.2},{\"round\":3,\"log\":597,\"cpu\":2.6886060014367104,\"memory\":118.22},{\"round\":3,\"log\":598,\"cpu\":0.5684769991785288,\"memory\":118.78},{\"round\":3,\"log\":599,\"cpu\":3.5603819992393255,\"memory\":122.87},{\"round\":3,\"log\":600,\"cpu\":0.7864859998226166,\"memory\":123.64},{\"round\":3,\"log\":601,\"cpu\":1.9569100011140108,\"memory\":125.69},{\"round\":3,\"log\":602,\"cpu\":0.4596969988197088,\"memory\":126.08},{\"round\":3,\"log\":603,\"cpu\":5.635051000863314,\"memory\":117.04},{\"round\":3,\"log\":604,\"cpu\":1.7353709992021322,\"memory\":118.74},{\"round\":3,\"log\":605,\"cpu\":3.9409700017422438,\"memory\":122.92},{\"round\":3,\"log\":606,\"cpu\":0.8242459986358881,\"memory\":123.66},{\"round\":3,\"log\":607,\"cpu\":5.460761001333594,\"memory\":115.58},{\"round\":3,\"log\":608,\"cpu\":1.3809129986912012,\"memory\":116.76},{\"round\":3,\"log\":609,\"cpu\":2.679696001112461,\"memory\":119.61},{\"round\":3,\"log\":610,\"cpu\":0.5648369994014502,\"memory\":120.14},{\"round\":3,\"log\":611,\"cpu\":5.522960999980569,\"memory\":126.61},{\"round\":3,\"log\":612,\"cpu\":2.927275000140071,\"memory\":115.62},{\"round\":3,\"log\":613,\"cpu\":3.8292410001158714,\"memory\":119.79},{\"round\":3,\"log\":614,\"cpu\":0.8940149992704391,\"memory\":120.62},{\"round\":3,\"log\":615,\"cpu\":4.5279760006815195,\"memory\":125.29},{\"round\":3,\"log\":616,\"cpu\":1.5100619997829199,\"memory\":126.54},{\"round\":3,\"log\":617,\"cpu\":3.4158229995518923,\"memory\":115.68},{\"round\":3,\"log\":618,\"cpu\":0.6293069999665022,\"memory\":116.27},{\"round\":3,\"log\":619,\"cpu\":5.740029999986291,\"memory\":122.74},{\"round\":3,\"log\":620,\"cpu\":0.11624900065362453,\"memory\":122.8},{\"round\":3,\"log\":621,\"cpu\":4.16936899907887,\"memory\":126.91},{\"round\":3,\"log\":622,\"cpu\":0.05067900009453297,\"memory\":126.93},{\"round\":3,\"log\":623,\"cpu\":5.262513000518084,\"memory\":117.36},{\"round\":3,\"log\":624,\"cpu\":0.0957190003246069,\"memory\":117.41},{\"round\":3,\"log\":625,\"cpu\":2.5372470002621412,\"memory\":120.21},{\"round\":3,\"log\":626,\"cpu\":0.04449999891221523,\"memory\":120.23},{\"round\":3,\"log\":627,\"cpu\":5.873350000008941,\"memory\":126.68},{\"round\":3,\"log\":628,\"cpu\":0.15561900101602077,\"memory\":126.77},{\"round\":3,\"log\":629,\"cpu\":4.607826000079513,\"memory\":117.93},{\"round\":3,\"log\":630,\"cpu\":0.08922000043094158,\"memory\":117.97},{\"round\":3,\"log\":631,\"cpu\":4.030378999188542,\"memory\":122.6},{\"round\":3,\"log\":632,\"cpu\":0.12378899939358234,\"memory\":122.67},{\"round\":3,\"log\":633,\"cpu\":2.711745999753475,\"memory\":125.45},{\"round\":3,\"log\":634,\"cpu\":0.08375000022351742,\"memory\":125.49},{\"round\":3,\"log\":635,\"cpu\":6.314517000690103,\"memory\":117.86},{\"round\":3,\"log\":636,\"cpu\":0.23694900050759315,\"memory\":118.02},{\"round\":3,\"log\":637,\"cpu\":3.563350999727845,\"memory\":122.03},{\"round\":3,\"log\":638,\"cpu\":0.12948999926447868,\"memory\":122.11},{\"round\":3,\"log\":639,\"cpu\":4.379657000303268,\"memory\":126.71},{\"round\":3,\"log\":640,\"cpu\":0.1872290000319481,\"memory\":126.83},{\"round\":3,\"log\":641,\"cpu\":3.3971420004963875,\"memory\":115.61},{\"round\":3,\"log\":642,\"cpu\":0.10651000030338764,\"memory\":115.68},{\"round\":3,\"log\":643,\"cpu\":5.392171999439597,\"memory\":122.09},{\"round\":3,\"log\":644,\"cpu\":0.3862580005079508,\"memory\":122.41},{\"round\":3,\"log\":645,\"cpu\":3.6136409994214773,\"memory\":126.27},{\"round\":3,\"log\":646,\"cpu\":0.20405899919569492,\"memory\":126.42},{\"round\":3,\"log\":647,\"cpu\":5.014324000105262,\"memory\":116.6},{\"round\":3,\"log\":648,\"cpu\":0.3076480012387037,\"memory\":116.83},{\"round\":3,\"log\":649,\"cpu\":2.3831580001860857,\"memory\":119.46},{\"round\":3,\"log\":650,\"cpu\":0.15534899942576885,\"memory\":119.57},{\"round\":3,\"log\":651,\"cpu\":5.702940000221133,\"memory\":125.94},{\"round\":3,\"log\":652,\"cpu\":0.05116000026464462,\"memory\":125.96},{\"round\":3,\"log\":653,\"cpu\":5.179493999108672,\"memory\":117.46},{\"round\":3,\"log\":654,\"cpu\":0.03681899979710579,\"memory\":117.47},{\"round\":3,\"log\":655,\"cpu\":4.044640000909567,\"memory\":122.35},{\"round\":3,\"log\":656,\"cpu\":0.04411899857223034,\"memory\":122.37},{\"round\":3,\"log\":657,\"cpu\":2.7381060011684895,\"memory\":125.19},{\"round\":3,\"log\":658,\"cpu\":0.03447999991476536,\"memory\":125.2},{\"round\":3,\"log\":659,\"cpu\":6.61502599902451,\"memory\":117.91},{\"round\":3,\"log\":660,\"cpu\":0.05857900157570839,\"memory\":117.94},{\"round\":3,\"log\":661,\"cpu\":3.8958599995821714,\"memory\":122.09},{\"round\":3,\"log\":662,\"cpu\":0.04033999890089035,\"memory\":122.1},{\"round\":3,\"log\":663,\"cpu\":4.573776001110673,\"memory\":126.76},{\"round\":3,\"log\":664,\"cpu\":0.05123999901115894,\"memory\":126.79},{\"round\":3,\"log\":665,\"cpu\":3.780860001221299,\"memory\":115.93},{\"round\":3,\"log\":666,\"cpu\":0.040539998561143875,\"memory\":115.95},{\"round\":3,\"log\":667,\"cpu\":5.474262000992894,\"memory\":122.42},{\"round\":3,\"log\":668,\"cpu\":0.06939899921417236,\"memory\":122.46},{\"round\":3,\"log\":669,\"cpu\":3.97719999961555,\"memory\":126.61},{\"round\":3,\"log\":670,\"cpu\":0.05076000094413757,\"memory\":126.63},{\"round\":3,\"log\":671,\"cpu\":4.961373999714851,\"memory\":117.27},{\"round\":3,\"log\":672,\"cpu\":0.06684000045061111,\"memory\":117.32},{\"round\":3,\"log\":673,\"cpu\":2.598115999251604,\"memory\":120.14},{\"round\":3,\"log\":674,\"cpu\":0.0448599997907877,\"memory\":120.16},{\"round\":3,\"log\":675,\"cpu\":5.849640000611544,\"memory\":126.62},{\"round\":3,\"log\":676,\"cpu\":0.10745899938046932,\"memory\":126.69},{\"round\":3,\"log\":677,\"cpu\":5.328833000734448,\"memory\":118.07},{\"round\":3,\"log\":678,\"cpu\":0.06485900096595287,\"memory\":118.11},{\"round\":3,\"log\":679,\"cpu\":4.0967689994722605,\"memory\":122.77},{\"round\":3,\"log\":680,\"cpu\":0.09448899887502193,\"memory\":122.84},{\"round\":3,\"log\":681,\"cpu\":2.649567000567913,\"memory\":125.66},{\"round\":3,\"log\":682,\"cpu\":0.06296900101006031,\"memory\":125.69},{\"round\":3,\"log\":683,\"cpu\":5.083463998511434,\"memory\":114.44},{\"round\":3,\"log\":684,\"cpu\":0.16875900141894817,\"memory\":114.51},{\"round\":3,\"log\":685,\"cpu\":0.14409899897873402,\"memory\":114.59},{\"round\":3,\"log\":686,\"cpu\":0.23856900073587894,\"memory\":114.73},{\"round\":3,\"log\":687,\"cpu\":0.24107799865305424,\"memory\":114.87},{\"round\":3,\"log\":688,\"cpu\":0.4253080002963543,\"memory\":115.12},{\"round\":3,\"log\":689,\"cpu\":0.4055679999291897,\"memory\":115.38},{\"round\":3,\"log\":690,\"cpu\":0.8132260013371706,\"memory\":115.9},{\"round\":3,\"log\":691,\"cpu\":0.1703989990055561,\"memory\":116.02},{\"round\":3,\"log\":692,\"cpu\":5.006784999743104,\"memory\":121.13},{\"round\":3,\"log\":693,\"cpu\":2.0855490006506443,\"memory\":122.85},{\"round\":3,\"log\":694,\"cpu\":6.218427000567317,\"memory\":115.48},{\"round\":3,\"log\":695,\"cpu\":1.0249349996447563,\"memory\":116.47},{\"round\":3,\"log\":696,\"cpu\":3.9531299993395805,\"memory\":121.31},{\"round\":3,\"log\":697,\"cpu\":0.7604559995234013,\"memory\":122.18},{\"round\":3,\"log\":698,\"cpu\":4.199568001553416,\"memory\":126.98},{\"round\":3,\"log\":699,\"cpu\":0.7660859990864992,\"memory\":127.84},{\"round\":3,\"log\":700,\"cpu\":18.19849600084126,\"memory\":122.54},{\"round\":3,\"log\":701,\"cpu\":11.714869000017643,\"memory\":123.76},{\"round\":3,\"log\":702,\"cpu\":2.0539299994707108,\"memory\":125.48},{\"round\":3,\"log\":703,\"cpu\":4.706244999542832,\"memory\":130.64},{\"round\":3,\"log\":704,\"cpu\":1.061914000660181,\"memory\":131.62},{\"round\":3,\"log\":705,\"cpu\":5.481591999530792,\"memory\":123.05},{\"round\":3,\"log\":706,\"cpu\":0.9924749992787838,\"memory\":123.92},{\"round\":3,\"log\":707,\"cpu\":4.505297001451254,\"memory\":128.72},{\"round\":3,\"log\":708,\"cpu\":0.7763860002160072,\"memory\":129.58},{\"round\":3,\"log\":709,\"cpu\":16.643222998827696,\"memory\":134.88},{\"round\":3,\"log\":710,\"cpu\":5.881640000268817,\"memory\":130.28},{\"round\":3,\"log\":711,\"cpu\":5.289011999964714,\"memory\":135.39},{\"round\":3,\"log\":712,\"cpu\":6.773245999589562,\"memory\":138.95},{\"round\":3,\"log\":713,\"cpu\":8.98458299972117,\"memory\":136.86},{\"round\":3,\"log\":714,\"cpu\":1.5822920016944408,\"memory\":138.63},{\"round\":3,\"log\":715,\"cpu\":6.476995998993516,\"memory\":133.35},{\"round\":3,\"log\":716,\"cpu\":1.1147140003740788,\"memory\":134.76},{\"round\":3,\"log\":717,\"cpu\":5.270162999629974,\"memory\":140.44},{\"round\":3,\"log\":718,\"cpu\":0.8817560002207756,\"memory\":141.67},{\"round\":3,\"log\":719,\"cpu\":7.025533000007272,\"memory\":134.97},{\"round\":3,\"log\":720,\"cpu\":0.11223899945616722,\"memory\":135.05},{\"round\":3,\"log\":721,\"cpu\":6.547947000712156,\"memory\":141.93},{\"round\":3,\"log\":722,\"cpu\":0.047119999304413795,\"memory\":141.95},{\"round\":3,\"log\":723,\"cpu\":5.9772880002856255,\"memory\":135.08},{\"round\":3,\"log\":724,\"cpu\":0.04532000049948692,\"memory\":135.09},{\"round\":3,\"log\":725,\"cpu\":5.247162999585271,\"memory\":140.77},{\"round\":3,\"log\":726,\"cpu\":0.04061000049114227,\"memory\":140.78},{\"round\":3,\"log\":727,\"cpu\":6.915543999522924,\"memory\":134.43},{\"round\":3,\"log\":728,\"cpu\":0.09454900026321411,\"memory\":134.51},{\"round\":3,\"log\":729,\"cpu\":6.669606000185013,\"memory\":141.39},{\"round\":3,\"log\":730,\"cpu\":0.04552999883890152,\"memory\":141.41},{\"round\":3,\"log\":731,\"cpu\":6.04241800121963,\"memory\":134.78},{\"round\":3,\"log\":732,\"cpu\":0.04325000010430813,\"memory\":134.79},{\"round\":3,\"log\":733,\"cpu\":5.26609299890697,\"memory\":140.47},{\"round\":3,\"log\":734,\"cpu\":0.04044000059366226,\"memory\":140.48},{\"round\":3,\"log\":735,\"cpu\":7.273431999608874,\"memory\":134.34},{\"round\":3,\"log\":736,\"cpu\":0.09475900046527386,\"memory\":134.42},{\"round\":3,\"log\":737,\"cpu\":6.58784699998796,\"memory\":141.29},{\"round\":3,\"log\":738,\"cpu\":0.06042899936437607,\"memory\":141.32},{\"round\":3,\"log\":739,\"cpu\":5.91609900072217,\"memory\":134.68},{\"round\":3,\"log\":740,\"cpu\":0.11146999895572662,\"memory\":134.77},{\"round\":3,\"log\":741,\"cpu\":5.023984000086784,\"memory\":140.36},{\"round\":3,\"log\":742,\"cpu\":0.18837900087237358,\"memory\":140.53},{\"round\":3,\"log\":743,\"cpu\":6.842024000361562,\"memory\":133.71},{\"round\":3,\"log\":744,\"cpu\":0.12110999971628189,\"memory\":133.79},{\"round\":3,\"log\":745,\"cpu\":6.585936000570655,\"memory\":140.66},{\"round\":3,\"log\":746,\"cpu\":0.06381999887526035,\"memory\":140.69},{\"round\":3,\"log\":747,\"cpu\":6.217357000336051,\"memory\":134.35},{\"round\":3,\"log\":748,\"cpu\":0.11016000062227249,\"memory\":134.44},{\"round\":3,\"log\":749,\"cpu\":4.851654998958111,\"memory\":140.02},{\"round\":3,\"log\":750,\"cpu\":0.17240899987518787,\"memory\":140.2},{\"round\":3,\"log\":751,\"cpu\":6.703735001385212,\"memory\":133.57},{\"round\":3,\"log\":752,\"cpu\":0.213578999042511,\"memory\":133.7},{\"round\":3,\"log\":753,\"cpu\":6.655656000599265,\"memory\":140.58},{\"round\":3,\"log\":754,\"cpu\":0.08071899972856045,\"memory\":140.63},{\"round\":3,\"log\":755,\"cpu\":5.962399000301957,\"memory\":134.37},{\"round\":3,\"log\":756,\"cpu\":0.1461589988321066,\"memory\":134.53},{\"round\":3,\"log\":757,\"cpu\":4.934415001422167,\"memory\":140.21},{\"round\":3,\"log\":758,\"cpu\":0.266397999599576,\"memory\":140.52},{\"round\":3,\"log\":759,\"cpu\":7.0205939989537,\"memory\":134.28},{\"round\":3,\"log\":760,\"cpu\":0.185589000582695,\"memory\":134.41},{\"round\":3,\"log\":761,\"cpu\":6.661755999550223,\"memory\":141.29},{\"round\":3,\"log\":762,\"cpu\":0.08040899969637394,\"memory\":141.34},{\"round\":3,\"log\":763,\"cpu\":6.141548000276089,\"memory\":134.72},{\"round\":3,\"log\":764,\"cpu\":0.147579001262784,\"memory\":134.88},{\"round\":3,\"log\":765,\"cpu\":5.212713999673724,\"memory\":140.56},{\"round\":3,\"log\":766,\"cpu\":0.25750800035893917,\"memory\":140.87},{\"round\":3,\"log\":767,\"cpu\":6.657185999676585,\"memory\":134.48},{\"round\":3,\"log\":768,\"cpu\":6.815804999321699,\"memory\":138.03},{\"round\":3,\"log\":769,\"cpu\":6.849713999778032,\"memory\":141.59},{\"round\":3,\"log\":770,\"cpu\":0.2187390010803938,\"memory\":141.74},{\"round\":3,\"log\":771,\"cpu\":0.21260899864137173,\"memory\":141.88},{\"round\":3,\"log\":772,\"cpu\":0.20787900127470493,\"memory\":142.01},{\"round\":3,\"log\":773,\"cpu\":0.2118180003017187,\"memory\":142.16},{\"round\":3,\"log\":774,\"cpu\":0.2009189985692501,\"memory\":142.3},{\"round\":3,\"log\":775,\"cpu\":118.95396500080824,\"memory\":178.71},{\"round\":3,\"log\":776,\"cpu\":0.05499899946153164,\"memory\":178.71},{\"round\":3,\"log\":777,\"cpu\":47.839122001081705,\"memory\":184.82},{\"round\":3,\"log\":778,\"cpu\":0.056939998641610146,\"memory\":184.82},{\"round\":3,\"log\":779,\"cpu\":3.9226700011640787,\"memory\":187.61},{\"round\":3,\"log\":780,\"cpu\":8.553434999659657,\"memory\":187.1},{\"round\":3,\"log\":781,\"cpu\":1.4215830005705357,\"memory\":188.22},{\"round\":3,\"log\":782,\"cpu\":2.9030449986457825,\"memory\":191.24},{\"round\":3,\"log\":783,\"cpu\":0.7012860011309385,\"memory\":191.8},{\"round\":3,\"log\":784,\"cpu\":3.975010000169277,\"memory\":195.89},{\"round\":3,\"log\":785,\"cpu\":0.984375,\"memory\":196.67},{\"round\":3,\"log\":786,\"cpu\":2.7250659987330437,\"memory\":184},{\"round\":3,\"log\":787,\"cpu\":6.422695999965072,\"memory\":190.65},{\"round\":3,\"log\":788,\"cpu\":1.4490729998797178,\"memory\":191.77},{\"round\":3,\"log\":789,\"cpu\":2.649846000596881,\"memory\":194.79},{\"round\":3,\"log\":790,\"cpu\":0.6309769991785288,\"memory\":195.35},{\"round\":3,\"log\":791,\"cpu\":4.465957000851631,\"memory\":185.23},{\"round\":3,\"log\":792,\"cpu\":0.8834649994969368,\"memory\":186},{\"round\":3,\"log\":793,\"cpu\":1.8031099997460842,\"memory\":188.05},{\"round\":3,\"log\":794,\"cpu\":0.4040580000728369,\"memory\":188.43},{\"round\":3,\"log\":795,\"cpu\":5.124174000695348,\"memory\":194.47},{\"round\":3,\"log\":796,\"cpu\":1.7540010008960962,\"memory\":196.17},{\"round\":3,\"log\":797,\"cpu\":5.355521999299526,\"memory\":188.12},{\"round\":3,\"log\":798,\"cpu\":0.7590459994971752,\"memory\":188.87},{\"round\":3,\"log\":799,\"cpu\":4.1904589999467134,\"memory\":193.54},{\"round\":3,\"log\":800,\"cpu\":1.3178930003196,\"memory\":194.72},{\"round\":3,\"log\":801,\"cpu\":2.8491149991750717,\"memory\":197.57},{\"round\":3,\"log\":802,\"cpu\":0.6402970012277365,\"memory\":198.1},{\"round\":3,\"log\":803,\"cpu\":6.203906999900937,\"memory\":189.89},{\"round\":3,\"log\":804,\"cpu\":1.9955799989402294,\"memory\":191.66},{\"round\":3,\"log\":805,\"cpu\":4.135879000648856,\"memory\":195.83},{\"round\":3,\"log\":806,\"cpu\":0.8068260010331869,\"memory\":196.66},{\"round\":3,\"log\":807,\"cpu\":5.058302998542786,\"memory\":187.7},{\"round\":3,\"log\":808,\"cpu\":1.3849929999560118,\"memory\":188.94},{\"round\":3,\"log\":809,\"cpu\":2.650977000594139,\"memory\":191.79},{\"round\":3,\"log\":810,\"cpu\":0.6085659991949797,\"memory\":192.38},{\"round\":3,\"log\":811,\"cpu\":6.8525350000709295,\"memory\":186.85},{\"round\":3,\"log\":812,\"cpu\":0.11808900162577629,\"memory\":186.91},{\"round\":3,\"log\":813,\"cpu\":3.7229410000145435,\"memory\":191.01},{\"round\":3,\"log\":814,\"cpu\":0.0493599995970726,\"memory\":191.04},{\"round\":3,\"log\":815,\"cpu\":4.367766998708248,\"memory\":195.68},{\"round\":3,\"log\":816,\"cpu\":0.0971900001168251,\"memory\":195.73},{\"round\":3,\"log\":817,\"cpu\":3.522791000083089,\"memory\":185.66},{\"round\":3,\"log\":818,\"cpu\":0.052880000323057175,\"memory\":185.67},{\"round\":3,\"log\":819,\"cpu\":5.804440001025796,\"memory\":192.13},{\"round\":3,\"log\":820,\"cpu\":0.1483789999037981,\"memory\":192.22},{\"round\":3,\"log\":821,\"cpu\":4.08920899964869,\"memory\":196.3},{\"round\":3,\"log\":822,\"cpu\":0.09889999963343143,\"memory\":196.34},{\"round\":3,\"log\":823,\"cpu\":5.016363000497222,\"memory\":187.39},{\"round\":3,\"log\":824,\"cpu\":0.13284999877214432,\"memory\":187.46},{\"round\":3,\"log\":825,\"cpu\":2.549057001248002,\"memory\":190.24},{\"round\":3,\"log\":826,\"cpu\":0.07901899889111519,\"memory\":190.28},{\"round\":3,\"log\":827,\"cpu\":5.947959000244737,\"memory\":196.71},{\"round\":3,\"log\":828,\"cpu\":0.2610290013253689,\"memory\":196.88},{\"round\":3,\"log\":829,\"cpu\":5.283702999353409,\"memory\":188.06},{\"round\":3,\"log\":830,\"cpu\":0.13298900052905083,\"memory\":188.14},{\"round\":3,\"log\":831,\"cpu\":4.083068998530507,\"memory\":192.73},{\"round\":3,\"log\":832,\"cpu\":0.17956900037825108,\"memory\":192.86},{\"round\":3,\"log\":833,\"cpu\":2.6389560010284185,\"memory\":195.59},{\"round\":3,\"log\":834,\"cpu\":0.11390999890863895,\"memory\":195.65},{\"round\":3,\"log\":835,\"cpu\":6.4655860010534525,\"memory\":188.4},{\"round\":3,\"log\":836,\"cpu\":0.40504799969494343,\"memory\":188.72},{\"round\":3,\"log\":837,\"cpu\":3.607881000265479,\"memory\":192.58},{\"round\":3,\"log\":838,\"cpu\":0.21560899913311005,\"memory\":192.74},{\"round\":3,\"log\":839,\"cpu\":4.457217000424862,\"memory\":197.26},{\"round\":3,\"log\":840,\"cpu\":0.3274479992687702,\"memory\":197.49},{\"round\":3,\"log\":841,\"cpu\":3.6559319999068975,\"memory\":186.06},{\"round\":3,\"log\":842,\"cpu\":0.16734900139272213,\"memory\":186.17},{\"round\":3,\"log\":843,\"cpu\":5.410931998863816,\"memory\":192.53},{\"round\":3,\"log\":844,\"cpu\":0.04931900091469288,\"memory\":192.56},{\"round\":3,\"log\":845,\"cpu\":3.8797599989920855,\"memory\":196.7},{\"round\":3,\"log\":846,\"cpu\":0.035420000553131104,\"memory\":196.71},{\"round\":3,\"log\":847,\"cpu\":5.204702999442816,\"memory\":187.7},{\"round\":3,\"log\":848,\"cpu\":0.04911999963223934,\"memory\":187.72},{\"round\":3,\"log\":849,\"cpu\":2.5700370017439127,\"memory\":190.55},{\"round\":3,\"log\":850,\"cpu\":0.03384999930858612,\"memory\":190.56},{\"round\":3,\"log\":851,\"cpu\":5.913228999823332,\"memory\":197.02},{\"round\":3,\"log\":852,\"cpu\":0.06115899980068207,\"memory\":197.05},{\"round\":3,\"log\":853,\"cpu\":5.374553000554442,\"memory\":188.54},{\"round\":3,\"log\":854,\"cpu\":0.04267000034451485,\"memory\":188.56},{\"round\":3,\"log\":855,\"cpu\":4.081517999991775,\"memory\":193.22},{\"round\":3,\"log\":856,\"cpu\":0.05260999873280525,\"memory\":193.25},{\"round\":3,\"log\":857,\"cpu\":2.8814150001853704,\"memory\":196.07},{\"round\":3,\"log\":858,\"cpu\":0.0406700000166893,\"memory\":196.08},{\"round\":3,\"log\":859,\"cpu\":6.425096999853849,\"memory\":188.73},{\"round\":3,\"log\":860,\"cpu\":0.07174000144004822,\"memory\":188.78},{\"round\":3,\"log\":861,\"cpu\":3.9252489991486073,\"memory\":192.92},{\"round\":3,\"log\":862,\"cpu\":0.05165000073611736,\"memory\":192.94},{\"round\":3,\"log\":863,\"cpu\":4.630756000056863,\"memory\":197.6},{\"round\":3,\"log\":864,\"cpu\":0.06900899857282639,\"memory\":197.64},{\"round\":3,\"log\":865,\"cpu\":4.0424889996647835,\"memory\":186.77},{\"round\":3,\"log\":866,\"cpu\":0.04795000143349171,\"memory\":186.79},{\"round\":3,\"log\":867,\"cpu\":5.474081998690963,\"memory\":193.27},{\"round\":3,\"log\":868,\"cpu\":0.10225900076329708,\"memory\":193.34},{\"round\":3,\"log\":869,\"cpu\":3.8453599996864796,\"memory\":197.48},{\"round\":3,\"log\":870,\"cpu\":0.0633700005710125,\"memory\":197.52},{\"round\":3,\"log\":871,\"cpu\":5.1646529994904995,\"memory\":188.12},{\"round\":3,\"log\":872,\"cpu\":0.13583900034427643,\"memory\":188.19},{\"round\":3,\"log\":873,\"cpu\":2.656706999987364,\"memory\":191.01},{\"round\":3,\"log\":874,\"cpu\":0.061538999900221825,\"memory\":191.04},{\"round\":3,\"log\":875,\"cpu\":4.39567800052464,\"memory\":193.98},{\"round\":3,\"log\":876,\"cpu\":0.18049899861216545,\"memory\":194.06},{\"round\":3,\"log\":877,\"cpu\":0.16233900003135204,\"memory\":194.14},{\"round\":3,\"log\":878,\"cpu\":0.24964900128543377,\"memory\":194.27},{\"round\":3,\"log\":879,\"cpu\":0.2353889998048544,\"memory\":194.41},{\"round\":3,\"log\":880,\"cpu\":0.5197969991713762,\"memory\":194.67},{\"round\":3,\"log\":881,\"cpu\":0.4429780002683401,\"memory\":194.92},{\"round\":3,\"log\":882,\"cpu\":0.8999450001865625,\"memory\":195.44},{\"round\":3,\"log\":883,\"cpu\":0.21783900074660778,\"memory\":195.56},{\"round\":3,\"log\":884,\"cpu\":6.178897999227047,\"memory\":187.28},{\"round\":3,\"log\":885,\"cpu\":1.8660300001502037,\"memory\":189},{\"round\":3,\"log\":886,\"cpu\":4.293767999857664,\"memory\":194.15},{\"round\":3,\"log\":887,\"cpu\":1.082804000005126,\"memory\":195.13},{\"round\":3,\"log\":888,\"cpu\":5.282432999461889,\"memory\":186.77},{\"round\":3,\"log\":889,\"cpu\":0.8205060008913279,\"memory\":187.64},{\"round\":3,\"log\":890,\"cpu\":4.007509000599384,\"memory\":192.44},{\"round\":3,\"log\":891,\"cpu\":0.7442759983241558,\"memory\":193.3},{\"round\":3,\"log\":892,\"cpu\":16.802493000403047,\"memory\":198.26},{\"round\":3,\"log\":893,\"cpu\":11.585699999704957,\"memory\":198.93},{\"round\":3,\"log\":894,\"cpu\":2.04954900033772,\"memory\":200.65},{\"round\":3,\"log\":895,\"cpu\":7.580640999600291,\"memory\":195.65},{\"round\":3,\"log\":896,\"cpu\":1.102835001423955,\"memory\":196.64},{\"round\":3,\"log\":897,\"cpu\":4.2470669988542795,\"memory\":201.48},{\"round\":3,\"log\":898,\"cpu\":0.8044960014522076,\"memory\":202.35},{\"round\":3,\"log\":899,\"cpu\":5.260852999985218,\"memory\":193.79},{\"round\":3,\"log\":900,\"cpu\":0.9397649988532066,\"memory\":194.65},{\"round\":3,\"log\":901,\"cpu\":17.206120999529958,\"memory\":202.65},{\"round\":3,\"log\":902,\"cpu\":3.718731001019478,\"memory\":205.42},{\"round\":3,\"log\":903,\"cpu\":5.753389999270439,\"memory\":195.59},{\"round\":3,\"log\":904,\"cpu\":6.8493240009993315,\"memory\":199.15},{\"round\":3,\"log\":905,\"cpu\":6.81500499881804,\"memory\":206.02},{\"round\":3,\"log\":906,\"cpu\":2.572807000949979,\"memory\":194.61},{\"round\":3,\"log\":907,\"cpu\":5.032363999634981,\"memory\":200.44},{\"round\":3,\"log\":908,\"cpu\":1.0181249994784594,\"memory\":201.85},{\"round\":3,\"log\":909,\"cpu\":6.037887999787927,\"memory\":196.28},{\"round\":3,\"log\":910,\"cpu\":0.9276850000023842,\"memory\":197.51},{\"round\":3,\"log\":911,\"cpu\":5.957129999995232,\"memory\":203.53},{\"round\":3,\"log\":912,\"cpu\":0.10985900089144707,\"memory\":203.61},{\"round\":3,\"log\":913,\"cpu\":7.3189320005476475,\"memory\":197.9},{\"round\":3,\"log\":914,\"cpu\":0.05199999921023846,\"memory\":197.92},{\"round\":3,\"log\":915,\"cpu\":5.289682000875473,\"memory\":203.75},{\"round\":3,\"log\":916,\"cpu\":0.047759998589754105,\"memory\":203.76},{\"round\":3,\"log\":917,\"cpu\":5.991879001259804,\"memory\":197.25},{\"round\":3,\"log\":918,\"cpu\":0.04358999989926815,\"memory\":197.26},{\"round\":3,\"log\":919,\"cpu\":6.126947999000549,\"memory\":203.28},{\"round\":3,\"log\":920,\"cpu\":0.0948099996894598,\"memory\":203.37},{\"round\":3,\"log\":921,\"cpu\":7.210971999913454,\"memory\":197.81},{\"round\":3,\"log\":922,\"cpu\":0.047040000557899475,\"memory\":197.83},{\"round\":3,\"log\":923,\"cpu\":5.347062001004815,\"memory\":203.66},{\"round\":3,\"log\":924,\"cpu\":0.04107999987900257,\"memory\":203.67},{\"round\":3,\"log\":925,\"cpu\":5.7182199992239475,\"memory\":197.24},{\"round\":3,\"log\":926,\"cpu\":0.042570000514388084,\"memory\":197.25},{\"round\":3,\"log\":927,\"cpu\":6.053369000554085,\"memory\":203.27},{\"round\":3,\"log\":928,\"cpu\":0.09838899970054626,\"memory\":203.35},{\"round\":3,\"log\":929,\"cpu\":7.216572999954224,\"memory\":197.76},{\"round\":3,\"log\":930,\"cpu\":0.059709999710321426,\"memory\":197.79},{\"round\":3,\"log\":931,\"cpu\":5.253023000434041,\"memory\":203.6},{\"round\":3,\"log\":932,\"cpu\":0.10686899907886982,\"memory\":203.69},{\"round\":3,\"log\":933,\"cpu\":5.690209999680519,\"memory\":196.99},{\"round\":3,\"log\":934,\"cpu\":0.17893899977207184,\"memory\":197.16},{\"round\":3,\"log\":935,\"cpu\":6.015239000320435,\"memory\":203.01},{\"round\":3,\"log\":936,\"cpu\":0.11077000014483929,\"memory\":203.09},{\"round\":3,\"log\":937,\"cpu\":7.240922000259161,\"memory\":197.63},{\"round\":3,\"log\":938,\"cpu\":0.060100000351667404,\"memory\":197.66},{\"round\":3,\"log\":939,\"cpu\":5.157243000343442,\"memory\":203.46},{\"round\":3,\"log\":940,\"cpu\":0.12017999961972237,\"memory\":203.55},{\"round\":3,\"log\":941,\"cpu\":5.469040999189019,\"memory\":196.89},{\"round\":3,\"log\":942,\"cpu\":0.17549900151789188,\"memory\":197.06},{\"round\":3,\"log\":943,\"cpu\":5.910219999030232,\"memory\":202.91},{\"round\":3,\"log\":944,\"cpu\":0.1915889997035265,\"memory\":203.04},{\"round\":3,\"log\":945,\"cpu\":7.26537200063467,\"memory\":197.64},{\"round\":3,\"log\":946,\"cpu\":0.08826999925076962,\"memory\":197.69},{\"round\":3,\"log\":947,\"cpu\":5.226513000205159,\"memory\":203.51},{\"round\":3,\"log\":948,\"cpu\":0.14009900018572807,\"memory\":203.67},{\"round\":3,\"log\":949,\"cpu\":5.841129999607801,\"memory\":197.22},{\"round\":3,\"log\":950,\"cpu\":0.24507900141179562,\"memory\":197.53},{\"round\":3,\"log\":951,\"cpu\":6.0935179982334375,\"memory\":203.55},{\"round\":3,\"log\":952,\"cpu\":0.1794190015643835,\"memory\":203.68},{\"round\":3,\"log\":953,\"cpu\":7.2062630001455545,\"memory\":197.94},{\"round\":3,\"log\":954,\"cpu\":0.0833589993417263,\"memory\":197.99},{\"round\":3,\"log\":955,\"cpu\":5.343051999807358,\"memory\":203.81},{\"round\":3,\"log\":956,\"cpu\":0.15376999974250793,\"memory\":203.97},{\"round\":3,\"log\":957,\"cpu\":5.721410000696778,\"memory\":197.4},{\"round\":3,\"log\":958,\"cpu\":0.2566689997911453,\"memory\":197.71},{\"round\":3,\"log\":959,\"cpu\":6.099347999319434,\"memory\":203.73},{\"round\":3,\"log\":960,\"cpu\":7.2389730010181665,\"memory\":193.95},{\"round\":3,\"log\":961,\"cpu\":6.8234939984977245,\"memory\":197.51},{\"round\":3,\"log\":962,\"cpu\":0.2156290002167225,\"memory\":197.65},{\"round\":3,\"log\":963,\"cpu\":0.20928900130093098,\"memory\":197.78},{\"round\":3,\"log\":964,\"cpu\":0.20108900032937527,\"memory\":197.92},{\"round\":3,\"log\":965,\"cpu\":0.21498899906873703,\"memory\":198.07},{\"round\":3,\"log\":966,\"cpu\":0.19067900069057941,\"memory\":198.21},{\"round\":3,\"log\":967,\"cpu\":144.220922999084,\"memory\":43.79},{\"round\":3,\"log\":968,\"cpu\":0.072180001065135,\"memory\":43.79},{\"round\":3,\"log\":969,\"cpu\":46.866126999258995,\"memory\":49.94},{\"round\":3,\"log\":970,\"cpu\":0.05623999983072281,\"memory\":49.94}],[{\"round\":4,\"log\":0,\"cpu\":17.537769000977278,\"memory\":9.93},{\"round\":4,\"log\":1,\"cpu\":2.133338999003172,\"memory\":11.4},{\"round\":4,\"log\":2,\"cpu\":0.17671900056302547,\"memory\":11.41},{\"round\":4,\"log\":3,\"cpu\":0.30770800076425076,\"memory\":11.44},{\"round\":4,\"log\":4,\"cpu\":0.11780999973416328,\"memory\":11.45},{\"round\":4,\"log\":5,\"cpu\":0.10370899923145771,\"memory\":11.47},{\"round\":4,\"log\":6,\"cpu\":0.05857999995350838,\"memory\":11.48},{\"round\":4,\"log\":7,\"cpu\":0.3009580001235008,\"memory\":11.61},{\"round\":4,\"log\":8,\"cpu\":0.108279999345541,\"memory\":11.63},{\"round\":4,\"log\":9,\"cpu\":0.17416900023818016,\"memory\":11.69},{\"round\":4,\"log\":10,\"cpu\":0.08982900157570839,\"memory\":11.71},{\"round\":4,\"log\":11,\"cpu\":1.1807539984583855,\"memory\":13.16},{\"round\":4,\"log\":12,\"cpu\":10.085098000243306,\"memory\":6.6},{\"round\":4,\"log\":13,\"cpu\":1.640132000669837,\"memory\":7.7},{\"round\":4,\"log\":14,\"cpu\":3.90815999917686,\"memory\":10.81},{\"round\":4,\"log\":15,\"cpu\":0.6955360006541014,\"memory\":11.36},{\"round\":4,\"log\":16,\"cpu\":5.19467299990356,\"memory\":15.52},{\"round\":4,\"log\":17,\"cpu\":2.477316999807954,\"memory\":3.95},{\"round\":4,\"log\":18,\"cpu\":2.6321869995445013,\"memory\":6.04},{\"round\":4,\"log\":19,\"cpu\":6.974633000791073,\"memory\":12.52},{\"round\":4,\"log\":20,\"cpu\":1.3482029996812344,\"memory\":13.61},{\"round\":4,\"log\":21,\"cpu\":3.244963999837637,\"memory\":16.66},{\"round\":4,\"log\":22,\"cpu\":0.6601360011845827,\"memory\":17.21},{\"round\":4,\"log\":23,\"cpu\":4.752765998244286,\"memory\":5.8},{\"round\":4,\"log\":24,\"cpu\":0.9477950017899275,\"memory\":6.55},{\"round\":4,\"log\":25,\"cpu\":2.164088999852538,\"memory\":8.61},{\"round\":4,\"log\":26,\"cpu\":0.4760469999164343,\"memory\":8.99},{\"round\":4,\"log\":27,\"cpu\":5.990358998999,\"memory\":15.04},{\"round\":4,\"log\":28,\"cpu\":2.216168999671936,\"memory\":16.73},{\"round\":4,\"log\":29,\"cpu\":6.104687999933958,\"memory\":8.23},{\"round\":4,\"log\":30,\"cpu\":0.8477549999952316,\"memory\":8.98},{\"round\":4,\"log\":31,\"cpu\":4.927365001291037,\"memory\":13.75},{\"round\":4,\"log\":32,\"cpu\":1.590981999412179,\"memory\":14.96},{\"round\":4,\"log\":33,\"cpu\":4.318088000640273,\"memory\":4.96},{\"round\":4,\"log\":34,\"cpu\":0.6967359986156225,\"memory\":5.5},{\"round\":4,\"log\":35,\"cpu\":6.664665000513196,\"memory\":12},{\"round\":4,\"log\":36,\"cpu\":2.1375290006399155,\"memory\":13.74},{\"round\":4,\"log\":37,\"cpu\":5.659490998834372,\"memory\":6.42},{\"round\":4,\"log\":38,\"cpu\":0.9365350008010864,\"memory\":7.25},{\"round\":4,\"log\":39,\"cpu\":4.788875000551343,\"memory\":11.92},{\"round\":4,\"log\":40,\"cpu\":1.6971819996833801,\"memory\":13.16},{\"round\":4,\"log\":41,\"cpu\":2.9080049991607666,\"memory\":15.99},{\"round\":4,\"log\":42,\"cpu\":0.7627260014414787,\"memory\":16.58},{\"round\":4,\"log\":43,\"cpu\":6.789003999903798,\"memory\":8.61},{\"round\":4,\"log\":44,\"cpu\":0.14869000017642975,\"memory\":8.67},{\"round\":4,\"log\":45,\"cpu\":4.286027999594808,\"memory\":12.75},{\"round\":4,\"log\":46,\"cpu\":0.05524899996817112,\"memory\":12.77},{\"round\":4,\"log\":47,\"cpu\":4.6757260002195835,\"memory\":17.42},{\"round\":4,\"log\":48,\"cpu\":0.11734899878501892,\"memory\":17.47},{\"round\":4,\"log\":49,\"cpu\":3.5295820012688637,\"memory\":6.44},{\"round\":4,\"log\":50,\"cpu\":0.05257999897003174,\"memory\":6.46},{\"round\":4,\"log\":51,\"cpu\":5.652541000396013,\"memory\":12.88},{\"round\":4,\"log\":52,\"cpu\":0.16557900048792362,\"memory\":12.98},{\"round\":4,\"log\":53,\"cpu\":3.9754389990121126,\"memory\":17.02},{\"round\":4,\"log\":54,\"cpu\":0.10095900110900402,\"memory\":17.07},{\"round\":4,\"log\":55,\"cpu\":4.937974998727441,\"memory\":7.37},{\"round\":4,\"log\":56,\"cpu\":0.1456190012395382,\"memory\":7.45},{\"round\":4,\"log\":57,\"cpu\":2.662796998396516,\"memory\":10.21},{\"round\":4,\"log\":58,\"cpu\":0.08701900020241737,\"memory\":10.24},{\"round\":4,\"log\":59,\"cpu\":6.083058001473546,\"memory\":16.65},{\"round\":4,\"log\":60,\"cpu\":0.25462899915874004,\"memory\":16.81},{\"round\":4,\"log\":61,\"cpu\":4.733426000922918,\"memory\":7.67},{\"round\":4,\"log\":62,\"cpu\":0.13820899836719036,\"memory\":7.75},{\"round\":4,\"log\":63,\"cpu\":4.153569001704454,\"memory\":12.33},{\"round\":4,\"log\":64,\"cpu\":0.19769899919629097,\"memory\":12.45},{\"round\":4,\"log\":65,\"cpu\":2.728694999590516,\"memory\":15.17},{\"round\":4,\"log\":66,\"cpu\":0.12433000095188618,\"memory\":15.23},{\"round\":4,\"log\":67,\"cpu\":6.444976000115275,\"memory\":7.77},{\"round\":4,\"log\":68,\"cpu\":0.46870799921453,\"memory\":8.08},{\"round\":4,\"log\":69,\"cpu\":3.654900999739766,\"memory\":11.92},{\"round\":4,\"log\":70,\"cpu\":0.2173089999705553,\"memory\":12.07},{\"round\":4,\"log\":71,\"cpu\":4.59935599938035,\"memory\":16.59},{\"round\":4,\"log\":72,\"cpu\":0.3415380008518696,\"memory\":16.81},{\"round\":4,\"log\":73,\"cpu\":3.3792829997837543,\"memory\":5.34},{\"round\":4,\"log\":74,\"cpu\":0.178549000993371,\"memory\":5.45},{\"round\":4,\"log\":75,\"cpu\":5.464681999757886,\"memory\":11.78},{\"round\":4,\"log\":76,\"cpu\":0.07384900003671646,\"memory\":11.81},{\"round\":4,\"log\":77,\"cpu\":3.8824599999934435,\"memory\":15.92},{\"round\":4,\"log\":78,\"cpu\":0.03863999992609024,\"memory\":15.94},{\"round\":4,\"log\":79,\"cpu\":5.342691998928785,\"memory\":6.91},{\"round\":4,\"log\":80,\"cpu\":0.05554000101983547,\"memory\":6.93},{\"round\":4,\"log\":81,\"cpu\":2.665446000173688,\"memory\":9.73},{\"round\":4,\"log\":82,\"cpu\":0.037629999220371246,\"memory\":9.74},{\"round\":4,\"log\":83,\"cpu\":6.011429000645876,\"memory\":16.17},{\"round\":4,\"log\":84,\"cpu\":0.07099900022149086,\"memory\":16.2},{\"round\":4,\"log\":85,\"cpu\":4.988894999027252,\"memory\":7.74},{\"round\":4,\"log\":86,\"cpu\":0.04941000044345856,\"memory\":7.76},{\"round\":4,\"log\":87,\"cpu\":4.14932799898088,\"memory\":12.41},{\"round\":4,\"log\":88,\"cpu\":0.06054000183939934,\"memory\":12.44},{\"round\":4,\"log\":89,\"cpu\":3.01074399985373,\"memory\":15.25},{\"round\":4,\"log\":90,\"cpu\":0.04870999976992607,\"memory\":15.27},{\"round\":4,\"log\":91,\"cpu\":6.313086999580264,\"memory\":8},{\"round\":4,\"log\":92,\"cpu\":0.08726000040769577,\"memory\":8.05},{\"round\":4,\"log\":93,\"cpu\":3.9202589988708496,\"memory\":12.16},{\"round\":4,\"log\":94,\"cpu\":0.0595100000500679,\"memory\":12.19},{\"round\":4,\"log\":95,\"cpu\":4.6425059996545315,\"memory\":16.83},{\"round\":4,\"log\":96,\"cpu\":0.0953500010073185,\"memory\":16.87},{\"round\":4,\"log\":97,\"cpu\":3.631021000444889,\"memory\":5.98},{\"round\":4,\"log\":98,\"cpu\":0.054979998618364334,\"memory\":6},{\"round\":4,\"log\":99,\"cpu\":5.532121000811458,\"memory\":12.43},{\"round\":4,\"log\":100,\"cpu\":0.11274899914860725,\"memory\":12.51},{\"round\":4,\"log\":101,\"cpu\":3.920540001243353,\"memory\":16.62},{\"round\":4,\"log\":102,\"cpu\":0.07011999934911728,\"memory\":16.65},{\"round\":4,\"log\":103,\"cpu\":4.977174000814557,\"memory\":7.3},{\"round\":4,\"log\":104,\"cpu\":0.11099899932742119,\"memory\":7.37},{\"round\":4,\"log\":105,\"cpu\":2.6047869995236397,\"memory\":10.17},{\"round\":4,\"log\":106,\"cpu\":0.06767000071704388,\"memory\":10.2},{\"round\":4,\"log\":107,\"cpu\":4.70970500074327,\"memory\":13.18},{\"round\":4,\"log\":108,\"cpu\":0.2095589991658926,\"memory\":13.25},{\"round\":4,\"log\":109,\"cpu\":0.15836899913847446,\"memory\":13.33},{\"round\":4,\"log\":110,\"cpu\":0.2742590010166168,\"memory\":13.47},{\"round\":4,\"log\":111,\"cpu\":0.2558980006724596,\"memory\":13.61},{\"round\":4,\"log\":112,\"cpu\":0.4682080000638962,\"memory\":13.87},{\"round\":4,\"log\":113,\"cpu\":0.46105799823999405,\"memory\":14.13},{\"round\":4,\"log\":114,\"cpu\":0.9026750009506941,\"memory\":14.65},{\"round\":4,\"log\":115,\"cpu\":0.20912900008261204,\"memory\":14.77},{\"round\":4,\"log\":116,\"cpu\":6.018819000571966,\"memory\":6.55},{\"round\":4,\"log\":117,\"cpu\":1.8857099991291761,\"memory\":8.24},{\"round\":4,\"log\":118,\"cpu\":4.6034859996289015,\"memory\":13.41},{\"round\":4,\"log\":119,\"cpu\":1.0403650011867285,\"memory\":14.37},{\"round\":4,\"log\":120,\"cpu\":5.358161998912692,\"memory\":6.05},{\"round\":4,\"log\":121,\"cpu\":0.8817549999803305,\"memory\":6.9},{\"round\":4,\"log\":122,\"cpu\":4.280998000875115,\"memory\":11.72},{\"round\":4,\"log\":123,\"cpu\":0.7540659997612238,\"memory\":12.55},{\"round\":4,\"log\":124,\"cpu\":17.21409099921584,\"memory\":17.61},{\"round\":4,\"log\":125,\"cpu\":11.586820000782609,\"memory\":18.2},{\"round\":4,\"log\":126,\"cpu\":1.951460000127554,\"memory\":19.89},{\"round\":4,\"log\":127,\"cpu\":6.683384999632835,\"memory\":15},{\"round\":4,\"log\":128,\"cpu\":1.0833250004798174,\"memory\":15.96},{\"round\":4,\"log\":129,\"cpu\":4.200848000124097,\"memory\":20.8},{\"round\":4,\"log\":130,\"cpu\":0.7991559989750385,\"memory\":21.64},{\"round\":4,\"log\":131,\"cpu\":4.895994000136852,\"memory\":13.07},{\"round\":4,\"log\":132,\"cpu\":0.9290260002017021,\"memory\":13.9},{\"round\":4,\"log\":133,\"cpu\":17.60014900006354,\"memory\":22.05},{\"round\":4,\"log\":134,\"cpu\":3.8702300004661083,\"memory\":24.73},{\"round\":4,\"log\":135,\"cpu\":5.586051000282168,\"memory\":14.92},{\"round\":4,\"log\":136,\"cpu\":7.239811999723315,\"memory\":18.53},{\"round\":4,\"log\":137,\"cpu\":7.121872998774052,\"memory\":25.37},{\"round\":4,\"log\":138,\"cpu\":2.42450800165534,\"memory\":13.93},{\"round\":4,\"log\":139,\"cpu\":4.966743998229504,\"memory\":19.72},{\"round\":4,\"log\":140,\"cpu\":1.026325000450015,\"memory\":21.11},{\"round\":4,\"log\":141,\"cpu\":6.162547999992967,\"memory\":15.58},{\"round\":4,\"log\":142,\"cpu\":0.9360450003296137,\"memory\":16.79},{\"round\":4,\"log\":143,\"cpu\":5.92348900064826,\"memory\":22.78},{\"round\":4,\"log\":144,\"cpu\":0.10159000009298325,\"memory\":22.86},{\"round\":4,\"log\":145,\"cpu\":7.819349000230432,\"memory\":17.25},{\"round\":4,\"log\":146,\"cpu\":0.059769999235868454,\"memory\":17.27},{\"round\":4,\"log\":147,\"cpu\":5.178092999383807,\"memory\":23.06},{\"round\":4,\"log\":148,\"cpu\":0.04464000090956688,\"memory\":23.08},{\"round\":4,\"log\":149,\"cpu\":6.289536999538541,\"memory\":16.61},{\"round\":4,\"log\":150,\"cpu\":0.04601000063121319,\"memory\":16.62},{\"round\":4,\"log\":151,\"cpu\":6.091018998995423,\"memory\":22.62},{\"round\":4,\"log\":152,\"cpu\":0.10022900067269802,\"memory\":22.7},{\"round\":4,\"log\":153,\"cpu\":7.546880999580026,\"memory\":17.15},{\"round\":4,\"log\":154,\"cpu\":0.05162000097334385,\"memory\":17.17},{\"round\":4,\"log\":155,\"cpu\":5.4342319983989,\"memory\":22.96},{\"round\":4,\"log\":156,\"cpu\":0.0418390017002821,\"memory\":22.98},{\"round\":4,\"log\":157,\"cpu\":5.793509999290109,\"memory\":16.58},{\"round\":4,\"log\":158,\"cpu\":0.05061999894678593,\"memory\":16.6},{\"round\":4,\"log\":159,\"cpu\":6.109069000929594,\"memory\":22.59},{\"round\":4,\"log\":160,\"cpu\":0.10110899992287159,\"memory\":22.67},{\"round\":4,\"log\":161,\"cpu\":7.2286729998886585,\"memory\":17.11},{\"round\":4,\"log\":162,\"cpu\":0.06367900036275387,\"memory\":17.13},{\"round\":4,\"log\":163,\"cpu\":5.307362999767065,\"memory\":22.91},{\"round\":4,\"log\":164,\"cpu\":0.10968999937176704,\"memory\":23},{\"round\":4,\"log\":165,\"cpu\":5.697410000488162,\"memory\":16.32},{\"round\":4,\"log\":166,\"cpu\":0.19633900001645088,\"memory\":16.49},{\"round\":4,\"log\":167,\"cpu\":5.870310001075268,\"memory\":22.32},{\"round\":4,\"log\":168,\"cpu\":0.1008789986371994,\"memory\":22.39},{\"round\":4,\"log\":169,\"cpu\":7.534060999751091,\"memory\":16.98},{\"round\":4,\"log\":170,\"cpu\":0.06453900039196014,\"memory\":17.01},{\"round\":4,\"log\":171,\"cpu\":5.246533000841737,\"memory\":22.78},{\"round\":4,\"log\":172,\"cpu\":0.12077999860048294,\"memory\":22.87},{\"round\":4,\"log\":173,\"cpu\":5.522731000557542,\"memory\":16.21},{\"round\":4,\"log\":174,\"cpu\":0.18778900057077408,\"memory\":16.38},{\"round\":4,\"log\":175,\"cpu\":6.069219000637531,\"memory\":22.2},{\"round\":4,\"log\":176,\"cpu\":0.19921899959445,\"memory\":22.33},{\"round\":4,\"log\":177,\"cpu\":7.42608099989593,\"memory\":16.98},{\"round\":4,\"log\":178,\"cpu\":0.09105999954044819,\"memory\":17.03},{\"round\":4,\"log\":179,\"cpu\":5.019384000450373,\"memory\":22.83},{\"round\":4,\"log\":180,\"cpu\":0.14277900010347366,\"memory\":22.98},{\"round\":4,\"log\":181,\"cpu\":5.794479999691248,\"memory\":16.52},{\"round\":4,\"log\":182,\"cpu\":0.25178899988532066,\"memory\":16.82},{\"round\":4,\"log\":183,\"cpu\":6.236356999725103,\"memory\":22.82},{\"round\":4,\"log\":184,\"cpu\":0.18140000104904175,\"memory\":22.95},{\"round\":4,\"log\":185,\"cpu\":7.07579299993813,\"memory\":17.3},{\"round\":4,\"log\":186,\"cpu\":0.08621899969875813,\"memory\":17.35},{\"round\":4,\"log\":187,\"cpu\":5.288603000342846,\"memory\":23.14},{\"round\":4,\"log\":188,\"cpu\":0.14637899957597256,\"memory\":23.3},{\"round\":4,\"log\":189,\"cpu\":5.681761000305414,\"memory\":16.73},{\"round\":4,\"log\":190,\"cpu\":0.2644589990377426,\"memory\":17.03},{\"round\":4,\"log\":191,\"cpu\":5.815919000655413,\"memory\":23.02},{\"round\":4,\"log\":192,\"cpu\":7.370122998952866,\"memory\":13.27},{\"round\":4,\"log\":193,\"cpu\":6.80566400103271,\"memory\":16.89},{\"round\":4,\"log\":194,\"cpu\":0.22212900035083294,\"memory\":17.02},{\"round\":4,\"log\":195,\"cpu\":0.21187900006771088,\"memory\":17.16},{\"round\":4,\"log\":196,\"cpu\":0.20671899989247322,\"memory\":17.29},{\"round\":4,\"log\":197,\"cpu\":0.21710899844765663,\"memory\":17.44},{\"round\":4,\"log\":198,\"cpu\":0.1923190001398325,\"memory\":17.58},{\"round\":4,\"log\":199,\"cpu\":120.95738400146365,\"memory\":58.17},{\"round\":4,\"log\":200,\"cpu\":0.05679900012910366,\"memory\":58.17},{\"round\":4,\"log\":201,\"cpu\":44.209291998296976,\"memory\":70.57},{\"round\":4,\"log\":202,\"cpu\":0.05345900170505047,\"memory\":70.57},{\"round\":4,\"log\":203,\"cpu\":6.208677999675274,\"memory\":65.93},{\"round\":4,\"log\":204,\"cpu\":5.752899998798966,\"memory\":71.97},{\"round\":4,\"log\":205,\"cpu\":1.27356400154531,\"memory\":73.05},{\"round\":4,\"log\":206,\"cpu\":3.028753999620676,\"memory\":76.07},{\"round\":4,\"log\":207,\"cpu\":0.5661069992929697,\"memory\":76.62},{\"round\":4,\"log\":208,\"cpu\":5.713780000805855,\"memory\":69.13},{\"round\":4,\"log\":209,\"cpu\":0.8600659985095263,\"memory\":69.89},{\"round\":4,\"log\":210,\"cpu\":2.097869001328945,\"memory\":71.93},{\"round\":4,\"log\":211,\"cpu\":6.3285370003432035,\"memory\":78.35},{\"round\":4,\"log\":212,\"cpu\":1.0841749999672174,\"memory\":79.44},{\"round\":4,\"log\":213,\"cpu\":3.222012998536229,\"memory\":67.54},{\"round\":4,\"log\":214,\"cpu\":0.7146760001778603,\"memory\":68.09},{\"round\":4,\"log\":215,\"cpu\":3.7520010005682707,\"memory\":72.18},{\"round\":4,\"log\":216,\"cpu\":0.753626000136137,\"memory\":72.93},{\"round\":4,\"log\":217,\"cpu\":1.8009200002998114,\"memory\":74.97},{\"round\":4,\"log\":218,\"cpu\":0.3925679996609688,\"memory\":75.35},{\"round\":4,\"log\":219,\"cpu\":5.995319999754429,\"memory\":68.43},{\"round\":4,\"log\":220,\"cpu\":1.8046300001442432,\"memory\":70.08},{\"round\":4,\"log\":221,\"cpu\":3.7386310007423162,\"memory\":74.22},{\"round\":4,\"log\":222,\"cpu\":0.7081259991973639,\"memory\":74.95},{\"round\":4,\"log\":223,\"cpu\":4.101408999413252,\"memory\":79.61},{\"round\":4,\"log\":224,\"cpu\":1.4997120015323162,\"memory\":80.78},{\"round\":4,\"log\":225,\"cpu\":3.588351998478174,\"memory\":69.93},{\"round\":4,\"log\":226,\"cpu\":0.5566269997507334,\"memory\":70.45},{\"round\":4,\"log\":227,\"cpu\":5.618701001629233,\"memory\":76.89},{\"round\":4,\"log\":228,\"cpu\":1.9443899989128113,\"memory\":78.62},{\"round\":4,\"log\":229,\"cpu\":5.122053001075983,\"memory\":70.6},{\"round\":4,\"log\":230,\"cpu\":0.7961659990251064,\"memory\":71.41},{\"round\":4,\"log\":231,\"cpu\":4.141309000551701,\"memory\":76.07},{\"round\":4,\"log\":232,\"cpu\":1.5553719997406006,\"memory\":77.3},{\"round\":4,\"log\":233,\"cpu\":2.9118140004575253,\"memory\":80.13},{\"round\":4,\"log\":234,\"cpu\":0.600246999412775,\"memory\":80.7},{\"round\":4,\"log\":235,\"cpu\":6.556677000597119,\"memory\":72.5},{\"round\":4,\"log\":236,\"cpu\":0.11119899898767471,\"memory\":72.56},{\"round\":4,\"log\":237,\"cpu\":3.9136100001633167,\"memory\":76.64},{\"round\":4,\"log\":238,\"cpu\":0.05168900080025196,\"memory\":76.66},{\"round\":4,\"log\":239,\"cpu\":5.283212998881936,\"memory\":68.82},{\"round\":4,\"log\":240,\"cpu\":0.10793900117278099,\"memory\":68.87},{\"round\":4,\"log\":241,\"cpu\":2.5611370000988245,\"memory\":71.65},{\"round\":4,\"log\":242,\"cpu\":0.044919999316334724,\"memory\":71.66},{\"round\":4,\"log\":243,\"cpu\":5.385771999135613,\"memory\":78.08},{\"round\":4,\"log\":244,\"cpu\":0.15661900117993355,\"memory\":78.17},{\"round\":4,\"log\":245,\"cpu\":5.21815299987793,\"memory\":70.19},{\"round\":4,\"log\":246,\"cpu\":0.09908000007271767,\"memory\":70.23},{\"round\":4,\"log\":247,\"cpu\":4.1635579988360405,\"memory\":74.85},{\"round\":4,\"log\":248,\"cpu\":0.12905000150203705,\"memory\":74.92},{\"round\":4,\"log\":249,\"cpu\":2.623665999621153,\"memory\":77.67},{\"round\":4,\"log\":250,\"cpu\":0.09325999952852726,\"memory\":77.71},{\"round\":4,\"log\":251,\"cpu\":6.539446000009775,\"memory\":70.75},{\"round\":4,\"log\":252,\"cpu\":0.2318580001592636,\"memory\":70.92},{\"round\":4,\"log\":253,\"cpu\":3.8303309995681047,\"memory\":74.9},{\"round\":4,\"log\":254,\"cpu\":0.12751900032162666,\"memory\":74.98},{\"round\":4,\"log\":255,\"cpu\":4.487777000293136,\"memory\":79.55},{\"round\":4,\"log\":256,\"cpu\":0.18196900002658367,\"memory\":79.67},{\"round\":4,\"log\":257,\"cpu\":3.6121209990233183,\"memory\":68.76},{\"round\":4,\"log\":258,\"cpu\":0.1131690014153719,\"memory\":68.82},{\"round\":4,\"log\":259,\"cpu\":5.408812999725342,\"memory\":75.2},{\"round\":4,\"log\":260,\"cpu\":0.3955680001527071,\"memory\":75.51},{\"round\":4,\"log\":261,\"cpu\":3.635570999234915,\"memory\":79.35},{\"round\":4,\"log\":262,\"cpu\":0.19566900096833706,\"memory\":79.5},{\"round\":4,\"log\":263,\"cpu\":4.961263999342918,\"memory\":69.96},{\"round\":4,\"log\":264,\"cpu\":0.32299800030887127,\"memory\":70.18},{\"round\":4,\"log\":265,\"cpu\":2.387057999148965,\"memory\":72.79},{\"round\":4,\"log\":266,\"cpu\":0.1591689996421337,\"memory\":72.9},{\"round\":4,\"log\":267,\"cpu\":5.6854910012334585,\"memory\":79.24},{\"round\":4,\"log\":268,\"cpu\":0.05464999936521053,\"memory\":79.26},{\"round\":4,\"log\":269,\"cpu\":4.767614999786019,\"memory\":70.93},{\"round\":4,\"log\":270,\"cpu\":0.039890000596642494,\"memory\":70.94},{\"round\":4,\"log\":271,\"cpu\":4.047519000247121,\"memory\":75.58},{\"round\":4,\"log\":272,\"cpu\":0.046469999477267265,\"memory\":75.61},{\"round\":4,\"log\":273,\"cpu\":2.6913259997963905,\"memory\":78.41},{\"round\":4,\"log\":274,\"cpu\":0.033800000324845314,\"memory\":78.42},{\"round\":4,\"log\":275,\"cpu\":6.660354999825358,\"memory\":71.19},{\"round\":4,\"log\":276,\"cpu\":0.062349000945687294,\"memory\":71.22},{\"round\":4,\"log\":277,\"cpu\":3.812830999493599,\"memory\":75.33},{\"round\":4,\"log\":278,\"cpu\":0.04394000023603439,\"memory\":75.35},{\"round\":4,\"log\":279,\"cpu\":4.448216998949647,\"memory\":79.99},{\"round\":4,\"log\":280,\"cpu\":0.06892899982631207,\"memory\":80.02},{\"round\":4,\"log\":281,\"cpu\":3.3800920005887747,\"memory\":69.2},{\"round\":4,\"log\":282,\"cpu\":0.04426000081002712,\"memory\":69.22},{\"round\":4,\"log\":283,\"cpu\":5.414183000102639,\"memory\":75.64},{\"round\":4,\"log\":284,\"cpu\":0.07331899926066399,\"memory\":75.68},{\"round\":4,\"log\":285,\"cpu\":3.864760000258684,\"memory\":79.79},{\"round\":4,\"log\":286,\"cpu\":0.052880000323057175,\"memory\":79.82},{\"round\":4,\"log\":287,\"cpu\":5.070433000102639,\"memory\":70.53},{\"round\":4,\"log\":288,\"cpu\":0.07455999962985516,\"memory\":70.57},{\"round\":4,\"log\":289,\"cpu\":2.5445370003581047,\"memory\":73.44},{\"round\":4,\"log\":290,\"cpu\":0.04690999910235405,\"memory\":73.46},{\"round\":4,\"log\":291,\"cpu\":5.615511000156403,\"memory\":79.88},{\"round\":4,\"log\":292,\"cpu\":0.11993899941444397,\"memory\":79.96},{\"round\":4,\"log\":293,\"cpu\":4.736506000161171,\"memory\":71.29},{\"round\":4,\"log\":294,\"cpu\":0.07051900029182434,\"memory\":71.33},{\"round\":4,\"log\":295,\"cpu\":4.041719000786543,\"memory\":75.97},{\"round\":4,\"log\":296,\"cpu\":0.10638999938964844,\"memory\":76.04},{\"round\":4,\"log\":297,\"cpu\":2.8121750000864267,\"memory\":78.84},{\"round\":4,\"log\":298,\"cpu\":0.06911000050604343,\"memory\":78.88},{\"round\":4,\"log\":299,\"cpu\":5.293832998722792,\"memory\":67.69},{\"round\":4,\"log\":300,\"cpu\":0.18995900079607964,\"memory\":67.76},{\"round\":4,\"log\":301,\"cpu\":0.14430899918079376,\"memory\":67.84},{\"round\":4,\"log\":302,\"cpu\":0.23591900058090687,\"memory\":67.98},{\"round\":4,\"log\":303,\"cpu\":0.23009900003671646,\"memory\":68.12},{\"round\":4,\"log\":304,\"cpu\":0.47074699960649014,\"memory\":68.38},{\"round\":4,\"log\":305,\"cpu\":0.43350800126791,\"memory\":68.63},{\"round\":4,\"log\":306,\"cpu\":0.8537949994206429,\"memory\":69.15},{\"round\":4,\"log\":307,\"cpu\":0.17864899896085262,\"memory\":69.27},{\"round\":4,\"log\":308,\"cpu\":5.129464000463486,\"memory\":74.62},{\"round\":4,\"log\":309,\"cpu\":1.9292099997401237,\"memory\":76.3},{\"round\":4,\"log\":310,\"cpu\":5.786550000309944,\"memory\":69.02},{\"round\":4,\"log\":311,\"cpu\":1.0747040007263422,\"memory\":69.98},{\"round\":4,\"log\":312,\"cpu\":3.92365999892354,\"memory\":74.82},{\"round\":4,\"log\":313,\"cpu\":0.7604060005396605,\"memory\":75.66},{\"round\":4,\"log\":314,\"cpu\":3.99813000112772,\"memory\":80.46},{\"round\":4,\"log\":315,\"cpu\":0.7397059984505177,\"memory\":81.29},{\"round\":4,\"log\":316,\"cpu\":17.746097000315785,\"memory\":76.22},{\"round\":4,\"log\":317,\"cpu\":11.277163000777364,\"memory\":77.29},{\"round\":4,\"log\":318,\"cpu\":1.9682989995926619,\"memory\":78.98},{\"round\":4,\"log\":319,\"cpu\":4.588476000353694,\"memory\":84.14},{\"round\":4,\"log\":320,\"cpu\":1.0330349989235401,\"memory\":85.09},{\"round\":4,\"log\":321,\"cpu\":5.259453000500798,\"memory\":76.68},{\"round\":4,\"log\":322,\"cpu\":0.9721949994564056,\"memory\":77.52},{\"round\":4,\"log\":323,\"cpu\":4.4967260006815195,\"memory\":82.32},{\"round\":4,\"log\":324,\"cpu\":0.7791659999638796,\"memory\":83.15},{\"round\":4,\"log\":325,\"cpu\":16.222617000341415,\"memory\":88.58},{\"round\":4,\"log\":326,\"cpu\":6.0514390002936125,\"memory\":83.82},{\"round\":4,\"log\":327,\"cpu\":5.06224299967289,\"memory\":88.93},{\"round\":4,\"log\":328,\"cpu\":6.633395999670029,\"memory\":92.46},{\"round\":4,\"log\":329,\"cpu\":9.116443000733852,\"memory\":90.22},{\"round\":4,\"log\":330,\"cpu\":1.6760909985750914,\"memory\":91.96},{\"round\":4,\"log\":331,\"cpu\":6.3560669999569654,\"memory\":86.86},{\"round\":4,\"log\":332,\"cpu\":1.1269840002059937,\"memory\":88.24},{\"round\":4,\"log\":333,\"cpu\":5.376382000744343,\"memory\":93.88},{\"round\":4,\"log\":334,\"cpu\":0.891295999288559,\"memory\":95.09},{\"round\":4,\"log\":335,\"cpu\":6.770345000550151,\"memory\":88.47},{\"round\":4,\"log\":336,\"cpu\":0.11064000055193901,\"memory\":88.55},{\"round\":4,\"log\":337,\"cpu\":6.532505000010133,\"memory\":95.4},{\"round\":4,\"log\":338,\"cpu\":0.050529999658465385,\"memory\":95.42},{\"round\":4,\"log\":339,\"cpu\":6.133938999846578,\"memory\":88.71},{\"round\":4,\"log\":340,\"cpu\":0.048298999667167664,\"memory\":88.72},{\"round\":4,\"log\":341,\"cpu\":5.079153999686241,\"memory\":94.37},{\"round\":4,\"log\":342,\"cpu\":0.04194900020956993,\"memory\":94.39},{\"round\":4,\"log\":343,\"cpu\":6.590216999873519,\"memory\":88.12},{\"round\":4,\"log\":344,\"cpu\":0.09552900120615959,\"memory\":88.2},{\"round\":4,\"log\":345,\"cpu\":6.657214999198914,\"memory\":95.05},{\"round\":4,\"log\":346,\"cpu\":0.048739999532699585,\"memory\":95.07},{\"round\":4,\"log\":347,\"cpu\":5.9607200007885695,\"memory\":88.53},{\"round\":4,\"log\":348,\"cpu\":0.04614900052547455,\"memory\":88.54},{\"round\":4,\"log\":349,\"cpu\":5.0963439997285604,\"memory\":94.19},{\"round\":4,\"log\":350,\"cpu\":0.04164999909698963,\"memory\":94.2},{\"round\":4,\"log\":351,\"cpu\":6.626585001125932,\"memory\":88},{\"round\":4,\"log\":352,\"cpu\":0.09703999944031239,\"memory\":88.07},{\"round\":4,\"log\":353,\"cpu\":6.67786500044167,\"memory\":94.92},{\"round\":4,\"log\":354,\"cpu\":0.06061000004410744,\"memory\":94.95},{\"round\":4,\"log\":355,\"cpu\":6.403356999158859,\"memory\":88.35},{\"round\":4,\"log\":356,\"cpu\":0.1130989994853735,\"memory\":88.44},{\"round\":4,\"log\":357,\"cpu\":4.933025000616908,\"memory\":94},{\"round\":4,\"log\":358,\"cpu\":0.19146900065243244,\"memory\":94.17},{\"round\":4,\"log\":359,\"cpu\":6.463325999677181,\"memory\":87.48},{\"round\":4,\"log\":360,\"cpu\":0.10652999952435493,\"memory\":87.56},{\"round\":4,\"log\":361,\"cpu\":6.601546000689268,\"memory\":94.4},{\"round\":4,\"log\":362,\"cpu\":0.06244899891316891,\"memory\":94.43},{\"round\":4,\"log\":363,\"cpu\":6.280138000845909,\"memory\":88.09},{\"round\":4,\"log\":364,\"cpu\":0.11400900036096573,\"memory\":88.17},{\"round\":4,\"log\":365,\"cpu\":4.873514998704195,\"memory\":93.73},{\"round\":4,\"log\":366,\"cpu\":0.18135900050401688,\"memory\":93.9},{\"round\":4,\"log\":367,\"cpu\":6.5092259999364614,\"memory\":87.29},{\"round\":4,\"log\":368,\"cpu\":0.21944900043308735,\"memory\":87.42},{\"round\":4,\"log\":369,\"cpu\":6.565605999901891,\"memory\":94.27},{\"round\":4,\"log\":370,\"cpu\":0.08177999965846539,\"memory\":94.32},{\"round\":4,\"log\":371,\"cpu\":6.005029000341892,\"memory\":88.1},{\"round\":4,\"log\":372,\"cpu\":0.14947899989783764,\"memory\":88.26},{\"round\":4,\"log\":373,\"cpu\":4.9609840009361506,\"memory\":93.9},{\"round\":4,\"log\":374,\"cpu\":0.26888899877667427,\"memory\":94.21},{\"round\":4,\"log\":375,\"cpu\":7.056454000994563,\"memory\":88.02},{\"round\":4,\"log\":376,\"cpu\":0.1893589999526739,\"memory\":88.15},{\"round\":4,\"log\":377,\"cpu\":6.7317049987614155,\"memory\":94.99},{\"round\":4,\"log\":378,\"cpu\":0.08084900118410587,\"memory\":95.04},{\"round\":4,\"log\":379,\"cpu\":5.856719998642802,\"memory\":88.44},{\"round\":4,\"log\":380,\"cpu\":0.15907900035381317,\"memory\":88.6},{\"round\":4,\"log\":381,\"cpu\":5.052044000476599,\"memory\":94.24},{\"round\":4,\"log\":382,\"cpu\":0.261608000844717,\"memory\":94.55},{\"round\":4,\"log\":383,\"cpu\":7.041363999247551,\"memory\":88.16},{\"round\":4,\"log\":384,\"cpu\":6.841944999992847,\"memory\":91.68},{\"round\":4,\"log\":385,\"cpu\":6.751815000548959,\"memory\":95.21},{\"round\":4,\"log\":386,\"cpu\":0.22543899901211262,\"memory\":95.35},{\"round\":4,\"log\":387,\"cpu\":0.21974899992346764,\"memory\":95.48},{\"round\":4,\"log\":388,\"cpu\":0.21719899959862232,\"memory\":95.62},{\"round\":4,\"log\":389,\"cpu\":0.22046800144016743,\"memory\":95.77},{\"round\":4,\"log\":390,\"cpu\":0.1965389996767044,\"memory\":95.9},{\"round\":4,\"log\":391,\"cpu\":130.03370800055563,\"memory\":45.5},{\"round\":4,\"log\":392,\"cpu\":0.06431899964809418,\"memory\":45.5},{\"round\":4,\"log\":393,\"cpu\":46.24770100042224,\"memory\":51.45},{\"round\":4,\"log\":394,\"cpu\":0.05565899983048439,\"memory\":51.45},{\"round\":4,\"log\":395,\"cpu\":3.9612199999392033,\"memory\":54.15},{\"round\":4,\"log\":396,\"cpu\":8.283686999231577,\"memory\":53.47},{\"round\":4,\"log\":397,\"cpu\":1.42064299993217,\"memory\":54.56},{\"round\":4,\"log\":398,\"cpu\":2.8192149996757507,\"memory\":57.58},{\"round\":4,\"log\":399,\"cpu\":0.5604270007461309,\"memory\":58.12},{\"round\":4,\"log\":400,\"cpu\":3.9254899993538857,\"memory\":62.21},{\"round\":4,\"log\":401,\"cpu\":1.860589999705553,\"memory\":50.77},{\"round\":4,\"log\":402,\"cpu\":2.0852290000766516,\"memory\":52.82},{\"round\":4,\"log\":403,\"cpu\":6.159779001027346,\"memory\":59.24},{\"round\":4,\"log\":404,\"cpu\":1.2055239994078875,\"memory\":60.33},{\"round\":4,\"log\":405,\"cpu\":2.77428499981761,\"memory\":63.35},{\"round\":4,\"log\":406,\"cpu\":1.400713000446558,\"memory\":49.7},{\"round\":4,\"log\":407,\"cpu\":3.706709999591112,\"memory\":53.79},{\"round\":4,\"log\":408,\"cpu\":0.8104159999638796,\"memory\":54.54},{\"round\":4,\"log\":409,\"cpu\":1.7716509997844696,\"memory\":56.59},{\"round\":4,\"log\":410,\"cpu\":0.40505800023674965,\"memory\":56.97},{\"round\":4,\"log\":411,\"cpu\":5.192503999918699,\"memory\":63},{\"round\":4,\"log\":412,\"cpu\":2.74766500107944,\"memory\":51.9},{\"round\":4,\"log\":413,\"cpu\":3.77432999946177,\"memory\":56.04},{\"round\":4,\"log\":414,\"cpu\":0.7157070003449917,\"memory\":56.78},{\"round\":4,\"log\":415,\"cpu\":4.254577999934554,\"memory\":61.43},{\"round\":4,\"log\":416,\"cpu\":1.5190919991582632,\"memory\":62.6},{\"round\":4,\"log\":417,\"cpu\":3.624761000275612,\"memory\":51.97},{\"round\":4,\"log\":418,\"cpu\":0.5668470002710819,\"memory\":52.49},{\"round\":4,\"log\":419,\"cpu\":5.607320999726653,\"memory\":58.93},{\"round\":4,\"log\":420,\"cpu\":1.964080000296235,\"memory\":60.66},{\"round\":4,\"log\":421,\"cpu\":5.405832000076771,\"memory\":53.07},{\"round\":4,\"log\":422,\"cpu\":0.8972249999642372,\"memory\":53.89},{\"round\":4,\"log\":423,\"cpu\":4.204899000003934,\"memory\":58.55},{\"round\":4,\"log\":424,\"cpu\":1.5189820006489754,\"memory\":59.77},{\"round\":4,\"log\":425,\"cpu\":2.8028349988162518,\"memory\":62.6},{\"round\":4,\"log\":426,\"cpu\":0.6189569998532534,\"memory\":63.18},{\"round\":4,\"log\":427,\"cpu\":6.386517001315951,\"memory\":55.09},{\"round\":4,\"log\":428,\"cpu\":0.11702900007367134,\"memory\":55.14},{\"round\":4,\"log\":429,\"cpu\":4.1328089982271194,\"memory\":59.22},{\"round\":4,\"log\":430,\"cpu\":0.05041000060737133,\"memory\":59.24},{\"round\":4,\"log\":431,\"cpu\":4.227498000487685,\"memory\":63.87},{\"round\":4,\"log\":432,\"cpu\":0.7472760006785393,\"memory\":50.23},{\"round\":4,\"log\":433,\"cpu\":2.6928359996527433,\"memory\":53.01},{\"round\":4,\"log\":434,\"cpu\":0.0466499999165535,\"memory\":53.02},{\"round\":4,\"log\":435,\"cpu\":5.353881999850273,\"memory\":59.44},{\"round\":4,\"log\":436,\"cpu\":0.1450789999216795,\"memory\":59.53},{\"round\":4,\"log\":437,\"cpu\":3.789410999044776,\"memory\":63.57},{\"round\":4,\"log\":438,\"cpu\":0.09556000120937824,\"memory\":63.62},{\"round\":4,\"log\":439,\"cpu\":4.668174998834729,\"memory\":53.9},{\"round\":4,\"log\":440,\"cpu\":0.12740000151097775,\"memory\":53.97},{\"round\":4,\"log\":441,\"cpu\":2.5229759998619556,\"memory\":56.72},{\"round\":4,\"log\":442,\"cpu\":0.07769999839365482,\"memory\":56.76},{\"round\":4,\"log\":443,\"cpu\":5.693811001256108,\"memory\":63.16},{\"round\":4,\"log\":444,\"cpu\":0.25912800058722496,\"memory\":63.32},{\"round\":4,\"log\":445,\"cpu\":5.222662998363376,\"memory\":54.24},{\"round\":4,\"log\":446,\"cpu\":0.12508000060915947,\"memory\":54.32},{\"round\":4,\"log\":447,\"cpu\":3.9334389995783567,\"memory\":58.9},{\"round\":4,\"log\":448,\"cpu\":0.1878490000963211,\"memory\":59.02},{\"round\":4,\"log\":449,\"cpu\":2.544167000800371,\"memory\":61.73},{\"round\":4,\"log\":450,\"cpu\":0.11168999969959259,\"memory\":61.79},{\"round\":4,\"log\":451,\"cpu\":6.4403159990906715,\"memory\":54.22},{\"round\":4,\"log\":452,\"cpu\":0.39830800145864487,\"memory\":54.53},{\"round\":4,\"log\":453,\"cpu\":3.522111998870969,\"memory\":58.37},{\"round\":4,\"log\":454,\"cpu\":0.21138899959623814,\"memory\":58.52},{\"round\":4,\"log\":455,\"cpu\":4.394067000597715,\"memory\":63.03},{\"round\":4,\"log\":456,\"cpu\":0.3236090000718832,\"memory\":63.25},{\"round\":4,\"log\":457,\"cpu\":3.2462930008769035,\"memory\":51.72},{\"round\":4,\"log\":458,\"cpu\":0.16512899845838547,\"memory\":51.83},{\"round\":4,\"log\":459,\"cpu\":5.24898200109601,\"memory\":58.16},{\"round\":4,\"log\":460,\"cpu\":0.06007000058889389,\"memory\":58.19},{\"round\":4,\"log\":461,\"cpu\":3.831870999187231,\"memory\":62.3},{\"round\":4,\"log\":462,\"cpu\":0.03715899959206581,\"memory\":62.31},{\"round\":4,\"log\":463,\"cpu\":5.094844000414014,\"memory\":53.27},{\"round\":4,\"log\":464,\"cpu\":0.05058000050485134,\"memory\":53.29},{\"round\":4,\"log\":465,\"cpu\":2.56929599866271,\"memory\":56.09},{\"round\":4,\"log\":466,\"cpu\":0.034620000049471855,\"memory\":56.11},{\"round\":4,\"log\":467,\"cpu\":5.7018210012465715,\"memory\":62.53},{\"round\":4,\"log\":468,\"cpu\":0.061058999970555305,\"memory\":62.56},{\"round\":4,\"log\":469,\"cpu\":4.704095998778939,\"memory\":54},{\"round\":4,\"log\":470,\"cpu\":0.0442500002682209,\"memory\":54.02},{\"round\":4,\"log\":471,\"cpu\":4.003848999738693,\"memory\":58.66},{\"round\":4,\"log\":472,\"cpu\":0.05282000079751015,\"memory\":58.69},{\"round\":4,\"log\":473,\"cpu\":2.6823759991675615,\"memory\":61.49},{\"round\":4,\"log\":474,\"cpu\":0.03888000175356865,\"memory\":61.5},{\"round\":4,\"log\":475,\"cpu\":6.302726998925209,\"memory\":54.21},{\"round\":4,\"log\":476,\"cpu\":0.1084000002592802,\"memory\":54.25},{\"round\":4,\"log\":477,\"cpu\":3.7895400002598763,\"memory\":58.36},{\"round\":4,\"log\":478,\"cpu\":0.05066999979317188,\"memory\":58.39},{\"round\":4,\"log\":479,\"cpu\":4.638496000319719,\"memory\":63.05},{\"round\":4,\"log\":480,\"cpu\":0.07818899862468243,\"memory\":63.09},{\"round\":4,\"log\":481,\"cpu\":4.033350000157952,\"memory\":52.2},{\"round\":4,\"log\":482,\"cpu\":0.048639001324772835,\"memory\":52.22},{\"round\":4,\"log\":483,\"cpu\":5.343831999227405,\"memory\":58.64},{\"round\":4,\"log\":484,\"cpu\":0.10910000093281269,\"memory\":58.72},{\"round\":4,\"log\":485,\"cpu\":3.938908999785781,\"memory\":62.83},{\"round\":4,\"log\":486,\"cpu\":0.0695899985730648,\"memory\":62.86},{\"round\":4,\"log\":487,\"cpu\":5.387333000078797,\"memory\":53.55},{\"round\":4,\"log\":488,\"cpu\":0.09973900020122528,\"memory\":53.62},{\"round\":4,\"log\":489,\"cpu\":2.518027000129223,\"memory\":56.42},{\"round\":4,\"log\":490,\"cpu\":0.06604900024831295,\"memory\":56.45},{\"round\":4,\"log\":491,\"cpu\":4.385447999462485,\"memory\":59.39},{\"round\":4,\"log\":492,\"cpu\":0.20744900032877922,\"memory\":59.47},{\"round\":4,\"log\":493,\"cpu\":0.1595690008252859,\"memory\":59.55},{\"round\":4,\"log\":494,\"cpu\":0.26033799909055233,\"memory\":59.68},{\"round\":4,\"log\":495,\"cpu\":0.23299900069832802,\"memory\":59.82},{\"round\":4,\"log\":496,\"cpu\":0.45407800003886223,\"memory\":60.08},{\"round\":4,\"log\":497,\"cpu\":0.43015800043940544,\"memory\":60.33},{\"round\":4,\"log\":498,\"cpu\":0.8780450001358986,\"memory\":60.85},{\"round\":4,\"log\":499,\"cpu\":0.2117689996957779,\"memory\":60.97},{\"round\":4,\"log\":500,\"cpu\":5.8891099989414215,\"memory\":52.69},{\"round\":4,\"log\":501,\"cpu\":1.7836899999529123,\"memory\":54.38},{\"round\":4,\"log\":502,\"cpu\":4.319548001512885,\"memory\":59.55},{\"round\":4,\"log\":503,\"cpu\":1.022444998845458,\"memory\":60.5},{\"round\":4,\"log\":504,\"cpu\":5.039494000375271,\"memory\":52.18},{\"round\":4,\"log\":505,\"cpu\":0.817816000431776,\"memory\":53.02},{\"round\":4,\"log\":506,\"cpu\":3.9930089991539717,\"memory\":57.84},{\"round\":4,\"log\":507,\"cpu\":0.737635999917984,\"memory\":58.67},{\"round\":4,\"log\":508,\"cpu\":16.965582000091672,\"memory\":63.76},{\"round\":4,\"log\":509,\"cpu\":10.885244000703096,\"memory\":64.33},{\"round\":4,\"log\":510,\"cpu\":2.014298999682069,\"memory\":66.02},{\"round\":4,\"log\":511,\"cpu\":6.467847000807524,\"memory\":61.06},{\"round\":4,\"log\":512,\"cpu\":1.0496549997478724,\"memory\":62.01},{\"round\":4,\"log\":513,\"cpu\":4.178937999531627,\"memory\":66.85},{\"round\":4,\"log\":514,\"cpu\":0.8026560004800558,\"memory\":67.7},{\"round\":4,\"log\":515,\"cpu\":3.96424899995327,\"memory\":72.5},{\"round\":4,\"log\":516,\"cpu\":2.110879000276327,\"memory\":59.99},{\"round\":4,\"log\":517,\"cpu\":17.406190998852253,\"memory\":68.16},{\"round\":4,\"log\":518,\"cpu\":4.007608000189066,\"memory\":70.83},{\"round\":4,\"log\":519,\"cpu\":5.457312000915408,\"memory\":61.08},{\"round\":4,\"log\":520,\"cpu\":7.01851399987936,\"memory\":64.6},{\"round\":4,\"log\":521,\"cpu\":6.875823998823762,\"memory\":71.45},{\"round\":4,\"log\":522,\"cpu\":2.713797001168132,\"memory\":59.97},{\"round\":4,\"log\":523,\"cpu\":5.009653998538852,\"memory\":65.76},{\"round\":4,\"log\":524,\"cpu\":1.0293439999222755,\"memory\":67.14},{\"round\":4,\"log\":525,\"cpu\":5.878760000690818,\"memory\":61.72},{\"round\":4,\"log\":526,\"cpu\":0.9254350010305643,\"memory\":62.93},{\"round\":4,\"log\":527,\"cpu\":5.931239999830723,\"memory\":68.92},{\"round\":4,\"log\":528,\"cpu\":0.10498899966478348,\"memory\":69},{\"round\":4,\"log\":529,\"cpu\":7.432200999930501,\"memory\":63.42},{\"round\":4,\"log\":530,\"cpu\":0.05429999902844429,\"memory\":63.44},{\"round\":4,\"log\":531,\"cpu\":5.111694000661373,\"memory\":69.24},{\"round\":4,\"log\":532,\"cpu\":0.04237999953329563,\"memory\":69.25},{\"round\":4,\"log\":533,\"cpu\":6.331446999683976,\"memory\":62.77},{\"round\":4,\"log\":534,\"cpu\":0.04655900038778782,\"memory\":62.79},{\"round\":4,\"log\":535,\"cpu\":5.878159999847412,\"memory\":68.78},{\"round\":4,\"log\":536,\"cpu\":0.08992000110447407,\"memory\":68.86},{\"round\":4,\"log\":537,\"cpu\":7.200651999562979,\"memory\":63.31},{\"round\":4,\"log\":538,\"cpu\":0.05031000077724457,\"memory\":63.33},{\"round\":4,\"log\":539,\"cpu\":5.421731999143958,\"memory\":69.13},{\"round\":4,\"log\":540,\"cpu\":0.041829999536275864,\"memory\":69.14},{\"round\":4,\"log\":541,\"cpu\":5.770589999854565,\"memory\":62.77},{\"round\":4,\"log\":542,\"cpu\":0.043800000101327896,\"memory\":62.78},{\"round\":4,\"log\":543,\"cpu\":6.222366999834776,\"memory\":68.78},{\"round\":4,\"log\":544,\"cpu\":0.1092700008302927,\"memory\":68.85},{\"round\":4,\"log\":545,\"cpu\":7.261952999979258,\"memory\":63.3},{\"round\":4,\"log\":546,\"cpu\":0.05932899937033653,\"memory\":63.33},{\"round\":4,\"log\":547,\"cpu\":5.228432999923825,\"memory\":69.1},{\"round\":4,\"log\":548,\"cpu\":0.11198900081217289,\"memory\":69.19},{\"round\":4,\"log\":549,\"cpu\":5.70898099988699,\"memory\":62.47},{\"round\":4,\"log\":550,\"cpu\":0.18072899989783764,\"memory\":62.64},{\"round\":4,\"log\":551,\"cpu\":5.908099999651313,\"memory\":68.49},{\"round\":4,\"log\":552,\"cpu\":0.09741900116205215,\"memory\":68.56},{\"round\":4,\"log\":553,\"cpu\":7.382061999291182,\"memory\":63.14},{\"round\":4,\"log\":554,\"cpu\":0.06690900027751923,\"memory\":63.17},{\"round\":4,\"log\":555,\"cpu\":5.293872999027371,\"memory\":68.95},{\"round\":4,\"log\":556,\"cpu\":0.125730000436306,\"memory\":69.04},{\"round\":4,\"log\":557,\"cpu\":5.94127899967134,\"memory\":62.38},{\"round\":4,\"log\":558,\"cpu\":0.1858390010893345,\"memory\":62.55},{\"round\":4,\"log\":559,\"cpu\":5.942568998783827,\"memory\":68.37},{\"round\":4,\"log\":560,\"cpu\":0.19809900037944317,\"memory\":68.5},{\"round\":4,\"log\":561,\"cpu\":7.519471000880003,\"memory\":63.13},{\"round\":4,\"log\":562,\"cpu\":0.08938999846577644,\"memory\":63.18},{\"round\":4,\"log\":563,\"cpu\":5.296552000567317,\"memory\":68.97},{\"round\":4,\"log\":564,\"cpu\":0.1441000010818243,\"memory\":69.13},{\"round\":4,\"log\":565,\"cpu\":5.992278998717666,\"memory\":62.73},{\"round\":4,\"log\":566,\"cpu\":0.25526800006628036,\"memory\":63.04},{\"round\":4,\"log\":567,\"cpu\":6.147018000483513,\"memory\":69.03},{\"round\":4,\"log\":568,\"cpu\":0.18959899991750717,\"memory\":69.16},{\"round\":4,\"log\":569,\"cpu\":7.739731000736356,\"memory\":63.51},{\"round\":4,\"log\":570,\"cpu\":0.08837899938225746,\"memory\":63.56},{\"round\":4,\"log\":571,\"cpu\":5.321852000430226,\"memory\":69.35},{\"round\":4,\"log\":572,\"cpu\":0.14419999904930592,\"memory\":69.51},{\"round\":4,\"log\":573,\"cpu\":5.762889999896288,\"memory\":62.9},{\"round\":4,\"log\":574,\"cpu\":0.25352900102734566,\"memory\":63.21},{\"round\":4,\"log\":575,\"cpu\":6.137127999216318,\"memory\":69.2},{\"round\":4,\"log\":576,\"cpu\":7.353922000154853,\"memory\":59.4},{\"round\":4,\"log\":577,\"cpu\":6.6193059999495745,\"memory\":62.93},{\"round\":4,\"log\":578,\"cpu\":0.2185180000960827,\"memory\":63.07},{\"round\":4,\"log\":579,\"cpu\":0.21004899963736534,\"memory\":63.21},{\"round\":4,\"log\":580,\"cpu\":0.20327899977564812,\"memory\":63.35},{\"round\":4,\"log\":581,\"cpu\":0.21103900112211704,\"memory\":63.49},{\"round\":4,\"log\":582,\"cpu\":0.18957899883389473,\"memory\":63.63},{\"round\":4,\"log\":583,\"cpu\":123.09352400153875,\"memory\":104},{\"round\":4,\"log\":584,\"cpu\":0.056838998571038246,\"memory\":104},{\"round\":4,\"log\":585,\"cpu\":43.803414000198245,\"memory\":116.49},{\"round\":4,\"log\":586,\"cpu\":0.055278999730944633,\"memory\":116.49},{\"round\":4,\"log\":587,\"cpu\":3.7612709999084473,\"memory\":119.18},{\"round\":4,\"log\":588,\"cpu\":8.613685000687838,\"memory\":117.89},{\"round\":4,\"log\":589,\"cpu\":1.2110239993780851,\"memory\":118.98},{\"round\":4,\"log\":590,\"cpu\":2.853295000270009,\"memory\":122},{\"round\":4,\"log\":591,\"cpu\":0.5690280012786388,\"memory\":122.54},{\"round\":4,\"log\":592,\"cpu\":5.683659998700023,\"memory\":115.11},{\"round\":4,\"log\":593,\"cpu\":0.9106860011816025,\"memory\":115.86},{\"round\":4,\"log\":594,\"cpu\":2.108618998900056,\"memory\":117.91},{\"round\":4,\"log\":595,\"cpu\":6.317377001047134,\"memory\":124.33},{\"round\":4,\"log\":596,\"cpu\":1.2717929985374212,\"memory\":125.42},{\"round\":4,\"log\":597,\"cpu\":3.207074001431465,\"memory\":113.55},{\"round\":4,\"log\":598,\"cpu\":0.7490759994834661,\"memory\":114.09},{\"round\":4,\"log\":599,\"cpu\":3.7267599999904633,\"memory\":118.18},{\"round\":4,\"log\":600,\"cpu\":0.8328060004860163,\"memory\":118.93},{\"round\":4,\"log\":601,\"cpu\":1.7593109998852015,\"memory\":120.98},{\"round\":4,\"log\":602,\"cpu\":0.3972379993647337,\"memory\":121.35},{\"round\":4,\"log\":603,\"cpu\":5.897679999470711,\"memory\":114.51},{\"round\":4,\"log\":604,\"cpu\":1.7525910008698702,\"memory\":116.15},{\"round\":4,\"log\":605,\"cpu\":3.7141599990427494,\"memory\":120.29},{\"round\":4,\"log\":606,\"cpu\":0.726927001029253,\"memory\":121.03},{\"round\":4,\"log\":607,\"cpu\":4.1730080004781485,\"memory\":125.68},{\"round\":4,\"log\":608,\"cpu\":1.5173519998788834,\"memory\":126.85},{\"round\":4,\"log\":609,\"cpu\":3.9519299995154142,\"memory\":115.96},{\"round\":4,\"log\":610,\"cpu\":0.5678170006722212,\"memory\":116.48},{\"round\":4,\"log\":611,\"cpu\":5.545240998268127,\"memory\":122.91},{\"round\":4,\"log\":612,\"cpu\":1.9105700012296438,\"memory\":124.64},{\"round\":4,\"log\":613,\"cpu\":5.5429819989949465,\"memory\":116.66},{\"round\":4,\"log\":614,\"cpu\":0.7844460010528564,\"memory\":117.47},{\"round\":4,\"log\":615,\"cpu\":4.126667998731136,\"memory\":122.13},{\"round\":4,\"log\":616,\"cpu\":1.489512000232935,\"memory\":123.35},{\"round\":4,\"log\":617,\"cpu\":2.8360760007053614,\"memory\":126.18},{\"round\":4,\"log\":618,\"cpu\":0.6048770006746054,\"memory\":126.76},{\"round\":4,\"log\":619,\"cpu\":6.700664998963475,\"memory\":118.51},{\"round\":4,\"log\":620,\"cpu\":0.12533999979496002,\"memory\":118.57},{\"round\":4,\"log\":621,\"cpu\":4.149508001282811,\"memory\":122.65},{\"round\":4,\"log\":622,\"cpu\":0.053088998422026634,\"memory\":122.67},{\"round\":4,\"log\":623,\"cpu\":5.3528230004012585,\"memory\":114.91},{\"round\":4,\"log\":624,\"cpu\":0.10997899994254112,\"memory\":114.96},{\"round\":4,\"log\":625,\"cpu\":2.5894070006906986,\"memory\":117.73},{\"round\":4,\"log\":626,\"cpu\":0.0454500000923872,\"memory\":117.75},{\"round\":4,\"log\":627,\"cpu\":5.381231999024749,\"memory\":124.17},{\"round\":4,\"log\":628,\"cpu\":0.1606189999729395,\"memory\":124.26},{\"round\":4,\"log\":629,\"cpu\":5.508932000026107,\"memory\":116.21},{\"round\":4,\"log\":630,\"cpu\":0.1109590008854866,\"memory\":116.26},{\"round\":4,\"log\":631,\"cpu\":4.152328999713063,\"memory\":120.87},{\"round\":4,\"log\":632,\"cpu\":0.12867899984121323,\"memory\":120.94},{\"round\":4,\"log\":633,\"cpu\":2.708416000008583,\"memory\":123.69},{\"round\":4,\"log\":634,\"cpu\":0.07555999979376793,\"memory\":123.73},{\"round\":4,\"log\":635,\"cpu\":6.4341160003095865,\"memory\":116.79},{\"round\":4,\"log\":636,\"cpu\":0.23019899986684322,\"memory\":116.95},{\"round\":4,\"log\":637,\"cpu\":3.806420000270009,\"memory\":120.94},{\"round\":4,\"log\":638,\"cpu\":0.1297600008547306,\"memory\":121.02},{\"round\":4,\"log\":639,\"cpu\":4.432016998529434,\"memory\":125.59},{\"round\":4,\"log\":640,\"cpu\":0.18777900002896786,\"memory\":125.71},{\"round\":4,\"log\":641,\"cpu\":3.593851000070572,\"memory\":114.79},{\"round\":4,\"log\":642,\"cpu\":0.1181889995932579,\"memory\":114.85},{\"round\":4,\"log\":643,\"cpu\":5.3081130012869835,\"memory\":121.23},{\"round\":4,\"log\":644,\"cpu\":0.38461799919605255,\"memory\":121.54},{\"round\":4,\"log\":645,\"cpu\":3.6798510011285543,\"memory\":125.38},{\"round\":4,\"log\":646,\"cpu\":0.19863899983465672,\"memory\":125.53},{\"round\":4,\"log\":647,\"cpu\":4.861974999308586,\"memory\":116},{\"round\":4,\"log\":648,\"cpu\":0.3173280004411936,\"memory\":116.22},{\"round\":4,\"log\":649,\"cpu\":2.357397999614477,\"memory\":118.83},{\"round\":4,\"log\":650,\"cpu\":0.15951899997889996,\"memory\":118.94},{\"round\":4,\"log\":651,\"cpu\":5.595931001007557,\"memory\":125.27},{\"round\":4,\"log\":652,\"cpu\":0.05342999845743179,\"memory\":125.3},{\"round\":4,\"log\":653,\"cpu\":4.769155001267791,\"memory\":116.99},{\"round\":4,\"log\":654,\"cpu\":0.038669999688863754,\"memory\":117},{\"round\":4,\"log\":655,\"cpu\":4.0282990001142025,\"memory\":121.65},{\"round\":4,\"log\":656,\"cpu\":0.046790000051259995,\"memory\":121.67},{\"round\":4,\"log\":657,\"cpu\":2.6889759991317987,\"memory\":124.47},{\"round\":4,\"log\":658,\"cpu\":0.03474000096321106,\"memory\":124.48},{\"round\":4,\"log\":659,\"cpu\":6.490265998989344,\"memory\":117.26},{\"round\":4,\"log\":660,\"cpu\":0.061160000041127205,\"memory\":117.29},{\"round\":4,\"log\":661,\"cpu\":3.7041309997439384,\"memory\":121.4},{\"round\":4,\"log\":662,\"cpu\":0.041270000860095024,\"memory\":121.42},{\"round\":4,\"log\":663,\"cpu\":4.285267999395728,\"memory\":126.06},{\"round\":4,\"log\":664,\"cpu\":0.05344900116324425,\"memory\":126.09},{\"round\":4,\"log\":665,\"cpu\":3.646271999925375,\"memory\":115.29},{\"round\":4,\"log\":666,\"cpu\":0.04130899906158447,\"memory\":115.31},{\"round\":4,\"log\":667,\"cpu\":5.32689299993217,\"memory\":121.73},{\"round\":4,\"log\":668,\"cpu\":0.06975900009274483,\"memory\":121.78},{\"round\":4,\"log\":669,\"cpu\":3.8776099998503923,\"memory\":125.89},{\"round\":4,\"log\":670,\"cpu\":0.047609999775886536,\"memory\":125.91},{\"round\":4,\"log\":671,\"cpu\":5.085934000089765,\"memory\":116.6},{\"round\":4,\"log\":672,\"cpu\":0.07036999985575676,\"memory\":116.64},{\"round\":4,\"log\":673,\"cpu\":2.516526000574231,\"memory\":119.45},{\"round\":4,\"log\":674,\"cpu\":0.04718000069260597,\"memory\":119.47},{\"round\":4,\"log\":675,\"cpu\":5.823099998757243,\"memory\":125.89},{\"round\":4,\"log\":676,\"cpu\":0.1170790009200573,\"memory\":125.96},{\"round\":4,\"log\":677,\"cpu\":4.672865999862552,\"memory\":117.36},{\"round\":4,\"log\":678,\"cpu\":0.06540000066161156,\"memory\":117.4},{\"round\":4,\"log\":679,\"cpu\":4.002448998391628,\"memory\":122.04},{\"round\":4,\"log\":680,\"cpu\":0.09823000058531761,\"memory\":122.11},{\"round\":4,\"log\":681,\"cpu\":2.6511659994721413,\"memory\":124.91},{\"round\":4,\"log\":682,\"cpu\":0.06218000128865242,\"memory\":124.95},{\"round\":4,\"log\":683,\"cpu\":5.29055199958384,\"memory\":113.72},{\"round\":4,\"log\":684,\"cpu\":0.17080900073051453,\"memory\":113.8},{\"round\":4,\"log\":685,\"cpu\":0.13960999995470047,\"memory\":113.88},{\"round\":4,\"log\":686,\"cpu\":0.23058799840509892,\"memory\":114.02},{\"round\":4,\"log\":687,\"cpu\":0.22240900062024593,\"memory\":114.16},{\"round\":4,\"log\":688,\"cpu\":0.4097980000078678,\"memory\":114.41},{\"round\":4,\"log\":689,\"cpu\":0.39504799991846085,\"memory\":114.67},{\"round\":4,\"log\":690,\"cpu\":0.7948860004544258,\"memory\":115.19},{\"round\":4,\"log\":691,\"cpu\":0.17184899933636189,\"memory\":115.31},{\"round\":4,\"log\":692,\"cpu\":4.890615001320839,\"memory\":120.42},{\"round\":4,\"log\":693,\"cpu\":2.029898999258876,\"memory\":122.11},{\"round\":4,\"log\":694,\"cpu\":5.900100000202656,\"memory\":114.87},{\"round\":4,\"log\":695,\"cpu\":1.1001340001821518,\"memory\":115.82},{\"round\":4,\"log\":696,\"cpu\":3.9229499995708466,\"memory\":120.66},{\"round\":4,\"log\":697,\"cpu\":0.7533560004085302,\"memory\":121.51},{\"round\":4,\"log\":698,\"cpu\":3.9728790000081062,\"memory\":126.31},{\"round\":4,\"log\":699,\"cpu\":0.8041660003364086,\"memory\":127.14},{\"round\":4,\"log\":700,\"cpu\":18.462814999744296,\"memory\":122.01},{\"round\":4,\"log\":701,\"cpu\":11.663409000262618,\"memory\":123.18},{\"round\":4,\"log\":702,\"cpu\":2.0139399990439415,\"memory\":124.87},{\"round\":4,\"log\":703,\"cpu\":4.667476000264287,\"memory\":130.02},{\"round\":4,\"log\":704,\"cpu\":0.9614349994808435,\"memory\":130.98},{\"round\":4,\"log\":705,\"cpu\":5.408021999523044,\"memory\":122.49},{\"round\":4,\"log\":706,\"cpu\":1.0307040009647608,\"memory\":123.33},{\"round\":4,\"log\":707,\"cpu\":4.407067999243736,\"memory\":128.14},{\"round\":4,\"log\":708,\"cpu\":0.7791959997266531,\"memory\":128.97},{\"round\":4,\"log\":709,\"cpu\":16.472265001386404,\"memory\":134.38},{\"round\":4,\"log\":710,\"cpu\":6.101528000086546,\"memory\":129.66},{\"round\":4,\"log\":711,\"cpu\":5.102663999423385,\"memory\":134.77},{\"round\":4,\"log\":712,\"cpu\":6.613415999338031,\"memory\":138.3},{\"round\":4,\"log\":713,\"cpu\":9.163742000237107,\"memory\":136.06},{\"round\":4,\"log\":714,\"cpu\":1.6719020009040833,\"memory\":137.8},{\"round\":4,\"log\":715,\"cpu\":6.566494999453425,\"memory\":132.67},{\"round\":4,\"log\":716,\"cpu\":1.1286239996552467,\"memory\":134.06},{\"round\":4,\"log\":717,\"cpu\":5.021855000406504,\"memory\":139.7},{\"round\":4,\"log\":718,\"cpu\":0.8808750007301569,\"memory\":140.91},{\"round\":4,\"log\":719,\"cpu\":7.02097399905324,\"memory\":134.28},{\"round\":4,\"log\":720,\"cpu\":0.10181899927556515,\"memory\":134.36},{\"round\":4,\"log\":721,\"cpu\":6.4845570009201765,\"memory\":141.21},{\"round\":4,\"log\":722,\"cpu\":0.049538999795913696,\"memory\":141.23},{\"round\":4,\"log\":723,\"cpu\":6.204067999497056,\"memory\":134.43},{\"round\":4,\"log\":724,\"cpu\":0.04473000019788742,\"memory\":134.45},{\"round\":4,\"log\":725,\"cpu\":5.024174001067877,\"memory\":140.1},{\"round\":4,\"log\":726,\"cpu\":0.040449999272823334,\"memory\":140.11},{\"round\":4,\"log\":727,\"cpu\":6.765675000846386,\"memory\":133.85},{\"round\":4,\"log\":728,\"cpu\":0.11690999940037727,\"memory\":133.93},{\"round\":4,\"log\":729,\"cpu\":6.580545000731945,\"memory\":140.78},{\"round\":4,\"log\":730,\"cpu\":0.04820999875664711,\"memory\":140.8},{\"round\":4,\"log\":731,\"cpu\":6.192148000001907,\"memory\":134.23},{\"round\":4,\"log\":732,\"cpu\":0.044350000098347664,\"memory\":134.25},{\"round\":4,\"log\":733,\"cpu\":5.149292999878526,\"memory\":139.89},{\"round\":4,\"log\":734,\"cpu\":0.041370000690221786,\"memory\":139.91},{\"round\":4,\"log\":735,\"cpu\":6.708385000005364,\"memory\":133.71},{\"round\":4,\"log\":736,\"cpu\":0.09548000060021877,\"memory\":133.79},{\"round\":4,\"log\":737,\"cpu\":6.571095999330282,\"memory\":140.63},{\"round\":4,\"log\":738,\"cpu\":0.056140000000596046,\"memory\":140.66},{\"round\":4,\"log\":739,\"cpu\":5.835509000346065,\"memory\":134.15},{\"round\":4,\"log\":740,\"cpu\":0.1121399998664856,\"memory\":134.23},{\"round\":4,\"log\":741,\"cpu\":4.739034999161959,\"memory\":139.79},{\"round\":4,\"log\":742,\"cpu\":0.17970900051295757,\"memory\":139.96},{\"round\":4,\"log\":743,\"cpu\":6.497556999325752,\"memory\":133.19},{\"round\":4,\"log\":744,\"cpu\":0.10111900046467781,\"memory\":133.27},{\"round\":4,\"log\":745,\"cpu\":6.396137000992894,\"memory\":140.11},{\"round\":4,\"log\":746,\"cpu\":0.058319998905062675,\"memory\":140.14},{\"round\":4,\"log\":747,\"cpu\":5.824039999395609,\"memory\":133.82},{\"round\":4,\"log\":748,\"cpu\":0.10993900150060654,\"memory\":133.9},{\"round\":4,\"log\":749,\"cpu\":4.899894999340177,\"memory\":139.46},{\"round\":4,\"log\":750,\"cpu\":0.19303900003433228,\"memory\":139.63},{\"round\":4,\"log\":751,\"cpu\":6.895424000918865,\"memory\":133.02},{\"round\":4,\"log\":752,\"cpu\":0.21898899972438812,\"memory\":133.15},{\"round\":4,\"log\":753,\"cpu\":6.4389059990644455,\"memory\":140},{\"round\":4,\"log\":754,\"cpu\":0.08036000095307827,\"memory\":140.05},{\"round\":4,\"log\":755,\"cpu\":5.969178998842835,\"memory\":133.82},{\"round\":4,\"log\":756,\"cpu\":0.14936000108718872,\"memory\":133.97},{\"round\":4,\"log\":757,\"cpu\":5.1001829989254475,\"memory\":139.62},{\"round\":4,\"log\":758,\"cpu\":0.25416900031268597,\"memory\":139.92},{\"round\":4,\"log\":759,\"cpu\":6.831265000626445,\"memory\":133.75},{\"round\":4,\"log\":760,\"cpu\":0.19048899970948696,\"memory\":133.88},{\"round\":4,\"log\":761,\"cpu\":6.5734160002321005,\"memory\":140.73},{\"round\":4,\"log\":762,\"cpu\":0.07893900014460087,\"memory\":140.78},{\"round\":4,\"log\":763,\"cpu\":6.033788999542594,\"memory\":134.18},{\"round\":4,\"log\":764,\"cpu\":0.15244900062680244,\"memory\":134.36},{\"round\":4,\"log\":765,\"cpu\":5.079993998631835,\"memory\":140},{\"round\":4,\"log\":766,\"cpu\":0.24778900109231472,\"memory\":140.31},{\"round\":4,\"log\":767,\"cpu\":6.657754998654127,\"memory\":133.93},{\"round\":4,\"log\":768,\"cpu\":6.952104000374675,\"memory\":137.45},{\"round\":4,\"log\":769,\"cpu\":6.812645001336932,\"memory\":140.99},{\"round\":4,\"log\":770,\"cpu\":0.2243989985436201,\"memory\":141.13},{\"round\":4,\"log\":771,\"cpu\":0.21902900002896786,\"memory\":141.27},{\"round\":4,\"log\":772,\"cpu\":0.2126190010458231,\"memory\":141.41},{\"round\":4,\"log\":773,\"cpu\":0.22203899919986725,\"memory\":141.56},{\"round\":4,\"log\":774,\"cpu\":0.19710900075733662,\"memory\":141.69},{\"round\":4,\"log\":775,\"cpu\":119.72889100015163,\"memory\":178.16},{\"round\":4,\"log\":776,\"cpu\":0.055618999525904655,\"memory\":178.16},{\"round\":4,\"log\":777,\"cpu\":46.47467000037432,\"memory\":184.17},{\"round\":4,\"log\":778,\"cpu\":0.053029999136924744,\"memory\":184.17},{\"round\":4,\"log\":779,\"cpu\":3.7899900004267693,\"memory\":186.86},{\"round\":4,\"log\":780,\"cpu\":9.48972100019455,\"memory\":186.33},{\"round\":4,\"log\":781,\"cpu\":1.3925330005586147,\"memory\":187.42},{\"round\":4,\"log\":782,\"cpu\":2.659585999324918,\"memory\":190.44},{\"round\":4,\"log\":783,\"cpu\":0.5799269992858171,\"memory\":190.98},{\"round\":4,\"log\":784,\"cpu\":3.793980000540614,\"memory\":195.07},{\"round\":4,\"log\":785,\"cpu\":0.8644459992647171,\"memory\":195.82},{\"round\":4,\"log\":786,\"cpu\":2.654116000980139,\"memory\":183.26},{\"round\":4,\"log\":787,\"cpu\":6.388738000765443,\"memory\":189.68},{\"round\":4,\"log\":788,\"cpu\":1.3310829997062683,\"memory\":190.77},{\"round\":4,\"log\":789,\"cpu\":2.6011759992688894,\"memory\":193.79},{\"round\":4,\"log\":790,\"cpu\":0.6240469999611378,\"memory\":194.33},{\"round\":4,\"log\":791,\"cpu\":4.687395000830293,\"memory\":184.41},{\"round\":4,\"log\":792,\"cpu\":0.9191359989345074,\"memory\":185.16},{\"round\":4,\"log\":793,\"cpu\":1.7695110011845827,\"memory\":187.21},{\"round\":4,\"log\":794,\"cpu\":0.3941079992800951,\"memory\":187.59},{\"round\":4,\"log\":795,\"cpu\":4.923164000734687,\"memory\":193.62},{\"round\":4,\"log\":796,\"cpu\":1.6279619988054037,\"memory\":195.27},{\"round\":4,\"log\":797,\"cpu\":5.130293000489473,\"memory\":187.31},{\"round\":4,\"log\":798,\"cpu\":0.7427660003304482,\"memory\":188.05},{\"round\":4,\"log\":799,\"cpu\":4.156918998807669,\"memory\":192.71},{\"round\":4,\"log\":800,\"cpu\":1.2948430012911558,\"memory\":193.87},{\"round\":4,\"log\":801,\"cpu\":2.8221849985420704,\"memory\":196.7},{\"round\":4,\"log\":802,\"cpu\":0.6592970006167889,\"memory\":197.23},{\"round\":4,\"log\":803,\"cpu\":6.250398000702262,\"memory\":189.05},{\"round\":4,\"log\":804,\"cpu\":2.0385389998555183,\"memory\":190.78},{\"round\":4,\"log\":805,\"cpu\":3.9922099988907576,\"memory\":194.92},{\"round\":4,\"log\":806,\"cpu\":0.7914760001003742,\"memory\":195.73},{\"round\":4,\"log\":807,\"cpu\":5.189013000577688,\"memory\":186.87},{\"round\":4,\"log\":808,\"cpu\":1.3755130004137754,\"memory\":188.1},{\"round\":4,\"log\":809,\"cpu\":2.61489599943161,\"memory\":190.93},{\"round\":4,\"log\":810,\"cpu\":0.6077069994062185,\"memory\":191.51},{\"round\":4,\"log\":811,\"cpu\":6.872125001624227,\"memory\":186.04},{\"round\":4,\"log\":812,\"cpu\":0.12507899850606918,\"memory\":186.1},{\"round\":4,\"log\":813,\"cpu\":3.7056100014597178,\"memory\":190.18},{\"round\":4,\"log\":814,\"cpu\":0.04966999962925911,\"memory\":190.2},{\"round\":4,\"log\":815,\"cpu\":4.249607998877764,\"memory\":194.83},{\"round\":4,\"log\":816,\"cpu\":0.09652000106871128,\"memory\":194.88},{\"round\":4,\"log\":817,\"cpu\":2.5664969999343157,\"memory\":197.65},{\"round\":4,\"log\":818,\"cpu\":0.04608999937772751,\"memory\":197.67},{\"round\":4,\"log\":819,\"cpu\":6.0087679997086525,\"memory\":189.38},{\"round\":4,\"log\":820,\"cpu\":0.16166900098323822,\"memory\":189.47},{\"round\":4,\"log\":821,\"cpu\":3.7940410003066063,\"memory\":193.52},{\"round\":4,\"log\":822,\"cpu\":0.09215899929404259,\"memory\":193.56},{\"round\":4,\"log\":823,\"cpu\":5.67527100071311,\"memory\":185.59},{\"round\":4,\"log\":824,\"cpu\":0.14176899939775467,\"memory\":185.67},{\"round\":4,\"log\":825,\"cpu\":2.5375369992107153,\"memory\":188.42},{\"round\":4,\"log\":826,\"cpu\":0.07621000148355961,\"memory\":188.46},{\"round\":4,\"log\":827,\"cpu\":5.325891999527812,\"memory\":194.86},{\"round\":4,\"log\":828,\"cpu\":0.21930900029838085,\"memory\":195.02},{\"round\":4,\"log\":829,\"cpu\":4.827834999188781,\"memory\":186.75},{\"round\":4,\"log\":830,\"cpu\":0.14087000116705894,\"memory\":186.83},{\"round\":4,\"log\":831,\"cpu\":4.1810079999268055,\"memory\":191.41},{\"round\":4,\"log\":832,\"cpu\":0.184859000146389,\"memory\":191.53},{\"round\":4,\"log\":833,\"cpu\":2.667885998263955,\"memory\":194.24},{\"round\":4,\"log\":834,\"cpu\":0.10388000123202801,\"memory\":194.3},{\"round\":4,\"log\":835,\"cpu\":6.819334000349045,\"memory\":187.36},{\"round\":4,\"log\":836,\"cpu\":0.40912799909710884,\"memory\":187.67},{\"round\":4,\"log\":837,\"cpu\":3.68321100063622,\"memory\":191.51},{\"round\":4,\"log\":838,\"cpu\":0.22451899945735931,\"memory\":191.66},{\"round\":4,\"log\":839,\"cpu\":4.274297999218106,\"memory\":196.17},{\"round\":4,\"log\":840,\"cpu\":0.340488001704216,\"memory\":196.39},{\"round\":4,\"log\":841,\"cpu\":3.44272199831903,\"memory\":185.24},{\"round\":4,\"log\":842,\"cpu\":0.17122900113463402,\"memory\":185.35},{\"round\":4,\"log\":843,\"cpu\":5.324992999434471,\"memory\":191.69},{\"round\":4,\"log\":844,\"cpu\":0.04959999956190586,\"memory\":191.71},{\"round\":4,\"log\":845,\"cpu\":3.9696890003979206,\"memory\":195.82},{\"round\":4,\"log\":846,\"cpu\":0.03766999952495098,\"memory\":195.83},{\"round\":4,\"log\":847,\"cpu\":5.249323001131415,\"memory\":186.96},{\"round\":4,\"log\":848,\"cpu\":0.050919000059366226,\"memory\":186.98},{\"round\":4,\"log\":849,\"cpu\":2.5764569994062185,\"memory\":189.79},{\"round\":4,\"log\":850,\"cpu\":0.03344999998807907,\"memory\":189.8},{\"round\":4,\"log\":851,\"cpu\":5.6884809993207455,\"memory\":196.22},{\"round\":4,\"log\":852,\"cpu\":0.055630000308156013,\"memory\":196.25},{\"round\":4,\"log\":853,\"cpu\":4.936143999919295,\"memory\":187.77},{\"round\":4,\"log\":854,\"cpu\":0.04313000105321407,\"memory\":187.79},{\"round\":4,\"log\":855,\"cpu\":4.03421900048852,\"memory\":192.43},{\"round\":4,\"log\":856,\"cpu\":0.05144899897277355,\"memory\":192.46},{\"round\":4,\"log\":857,\"cpu\":2.7773560006171465,\"memory\":195.26},{\"round\":4,\"log\":858,\"cpu\":0.03937999904155731,\"memory\":195.28},{\"round\":4,\"log\":859,\"cpu\":6.471746999770403,\"memory\":188.02},{\"round\":4,\"log\":860,\"cpu\":0.07606900110840797,\"memory\":188.07},{\"round\":4,\"log\":861,\"cpu\":3.8935499992221594,\"memory\":192.18},{\"round\":4,\"log\":862,\"cpu\":0.05240900069475174,\"memory\":192.2},{\"round\":4,\"log\":863,\"cpu\":4.610696999356151,\"memory\":196.84},{\"round\":4,\"log\":864,\"cpu\":0.06877000071108341,\"memory\":196.88},{\"round\":4,\"log\":865,\"cpu\":4.1503180004656315,\"memory\":186.05},{\"round\":4,\"log\":866,\"cpu\":0.049389999359846115,\"memory\":186.07},{\"round\":4,\"log\":867,\"cpu\":5.3599820006638765,\"memory\":192.49},{\"round\":4,\"log\":868,\"cpu\":0.10701999999582767,\"memory\":192.57},{\"round\":4,\"log\":869,\"cpu\":3.9690089989453554,\"memory\":196.68},{\"round\":4,\"log\":870,\"cpu\":0.1670290008187294,\"memory\":196.72},{\"round\":4,\"log\":871,\"cpu\":5.243742998689413,\"memory\":187.35},{\"round\":4,\"log\":872,\"cpu\":0.11789000034332275,\"memory\":187.42},{\"round\":4,\"log\":873,\"cpu\":2.615156000480056,\"memory\":190.22},{\"round\":4,\"log\":874,\"cpu\":0.06258999928832054,\"memory\":190.32},{\"round\":4,\"log\":875,\"cpu\":4.338496999815106,\"memory\":193.25},{\"round\":4,\"log\":876,\"cpu\":0.1800490003079176,\"memory\":193.33},{\"round\":4,\"log\":877,\"cpu\":0.15350900031626225,\"memory\":193.41},{\"round\":4,\"log\":878,\"cpu\":0.24978899955749512,\"memory\":193.55},{\"round\":4,\"log\":879,\"cpu\":0.24950900115072727,\"memory\":193.68},{\"round\":4,\"log\":880,\"cpu\":0.47943699918687344,\"memory\":193.94},{\"round\":4,\"log\":881,\"cpu\":0.4390779994428158,\"memory\":194.2},{\"round\":4,\"log\":882,\"cpu\":0.8930150009691715,\"memory\":194.71},{\"round\":4,\"log\":883,\"cpu\":0.1976890005171299,\"memory\":194.83},{\"round\":4,\"log\":884,\"cpu\":6.301787998527288,\"memory\":186.61},{\"round\":4,\"log\":885,\"cpu\":1.8548110015690327,\"memory\":188.29},{\"round\":4,\"log\":886,\"cpu\":4.263647999614477,\"memory\":193.45},{\"round\":4,\"log\":887,\"cpu\":1.0046939998865128,\"memory\":194.4},{\"round\":4,\"log\":888,\"cpu\":5.180173000320792,\"memory\":186.12},{\"round\":4,\"log\":889,\"cpu\":0.8559759985655546,\"memory\":186.96},{\"round\":4,\"log\":890,\"cpu\":3.942630000412464,\"memory\":191.76},{\"round\":4,\"log\":891,\"cpu\":0.7324260007590055,\"memory\":192.59},{\"round\":4,\"log\":892,\"cpu\":16.51270500011742,\"memory\":197.63},{\"round\":4,\"log\":893,\"cpu\":11.07210199907422,\"memory\":198.15},{\"round\":4,\"log\":894,\"cpu\":2.0718200001865625,\"memory\":199.84},{\"round\":4,\"log\":895,\"cpu\":6.543506000190973,\"memory\":194.93},{\"round\":4,\"log\":896,\"cpu\":1.0148639995604753,\"memory\":195.88},{\"round\":4,\"log\":897,\"cpu\":4.46004700101912,\"memory\":200.72},{\"round\":4,\"log\":898,\"cpu\":0.8769659996032715,\"memory\":201.56},{\"round\":4,\"log\":899,\"cpu\":4.21704800054431,\"memory\":206.37},{\"round\":4,\"log\":900,\"cpu\":2.18520899862051,\"memory\":193.84},{\"round\":4,\"log\":901,\"cpu\":17.339360000565648,\"memory\":202.01},{\"round\":4,\"log\":902,\"cpu\":3.7878700010478497,\"memory\":204.69},{\"round\":4,\"log\":903,\"cpu\":5.614281998947263,\"memory\":194.87},{\"round\":4,\"log\":904,\"cpu\":7.106932999566197,\"memory\":198.4},{\"round\":4,\"log\":905,\"cpu\":6.81029500067234,\"memory\":205.25},{\"round\":4,\"log\":906,\"cpu\":2.4548170007765293,\"memory\":193.8},{\"round\":4,\"log\":907,\"cpu\":5.007283998653293,\"memory\":199.59},{\"round\":4,\"log\":908,\"cpu\":1.0434540007263422,\"memory\":200.97},{\"round\":4,\"log\":909,\"cpu\":6.7633359991014,\"memory\":195.52},{\"round\":4,\"log\":910,\"cpu\":0.9406749997287989,\"memory\":196.73},{\"round\":4,\"log\":911,\"cpu\":5.890129001811147,\"memory\":202.72},{\"round\":4,\"log\":912,\"cpu\":0.10638999938964844,\"memory\":202.8},{\"round\":4,\"log\":913,\"cpu\":7.671229999512434,\"memory\":197.2},{\"round\":4,\"log\":914,\"cpu\":0.05529000051319599,\"memory\":197.22},{\"round\":4,\"log\":915,\"cpu\":5.2671830002218485,\"memory\":203.02},{\"round\":4,\"log\":916,\"cpu\":0.04129999876022339,\"memory\":203.03},{\"round\":4,\"log\":917,\"cpu\":5.938059000298381,\"memory\":196.63},{\"round\":4,\"log\":918,\"cpu\":0.042719000950455666,\"memory\":196.65},{\"round\":4,\"log\":919,\"cpu\":6.171878999099135,\"memory\":202.64},{\"round\":4,\"log\":920,\"cpu\":0.09699900075793266,\"memory\":202.72},{\"round\":4,\"log\":921,\"cpu\":7.560790998861194,\"memory\":197.15},{\"round\":4,\"log\":922,\"cpu\":0.04829900152981281,\"memory\":197.17},{\"round\":4,\"log\":923,\"cpu\":5.266362998634577,\"memory\":202.97},{\"round\":4,\"log\":924,\"cpu\":0.03831000067293644,\"memory\":202.98},{\"round\":4,\"log\":925,\"cpu\":5.743290999904275,\"memory\":196.62},{\"round\":4,\"log\":926,\"cpu\":0.04162999987602234,\"memory\":196.63},{\"round\":4,\"log\":927,\"cpu\":6.218816999346018,\"memory\":202.63},{\"round\":4,\"log\":928,\"cpu\":0.10293000005185604,\"memory\":202.7},{\"round\":4,\"log\":929,\"cpu\":7.26766199991107,\"memory\":197.15},{\"round\":4,\"log\":930,\"cpu\":0.0579800009727478,\"memory\":197.18},{\"round\":4,\"log\":931,\"cpu\":5.303362999111414,\"memory\":202.96},{\"round\":4,\"log\":932,\"cpu\":0.11013900116086006,\"memory\":203.04},{\"round\":4,\"log\":933,\"cpu\":5.958488998934627,\"memory\":196.36},{\"round\":4,\"log\":934,\"cpu\":0.19881900027394295,\"memory\":196.53},{\"round\":4,\"log\":935,\"cpu\":6.047338999807835,\"memory\":202.35},{\"round\":4,\"log\":936,\"cpu\":0.10032900050282478,\"memory\":202.43},{\"round\":4,\"log\":937,\"cpu\":7.476100999861956,\"memory\":197},{\"round\":4,\"log\":938,\"cpu\":0.06063999980688095,\"memory\":197.03},{\"round\":4,\"log\":939,\"cpu\":5.261693000793457,\"memory\":202.81},{\"round\":4,\"log\":940,\"cpu\":0.1124699991196394,\"memory\":202.89},{\"round\":4,\"log\":941,\"cpu\":5.809508999809623,\"memory\":196.26},{\"round\":4,\"log\":942,\"cpu\":0.17764000035822392,\"memory\":196.43},{\"round\":4,\"log\":943,\"cpu\":5.9206990003585815,\"memory\":202.25},{\"round\":4,\"log\":944,\"cpu\":0.20252900011837482,\"memory\":202.38},{\"round\":4,\"log\":945,\"cpu\":7.501610999926925,\"memory\":196.97},{\"round\":4,\"log\":946,\"cpu\":0.08903999999165535,\"memory\":197.02},{\"round\":4,\"log\":947,\"cpu\":5.120143000036478,\"memory\":202.81},{\"round\":4,\"log\":948,\"cpu\":0.14325900003314018,\"memory\":202.97},{\"round\":4,\"log\":949,\"cpu\":6.065919000655413,\"memory\":196.59},{\"round\":4,\"log\":950,\"cpu\":0.2601789999753237,\"memory\":196.89},{\"round\":4,\"log\":951,\"cpu\":6.195456998422742,\"memory\":202.88},{\"round\":4,\"log\":952,\"cpu\":0.18316900171339512,\"memory\":203.01},{\"round\":4,\"log\":953,\"cpu\":7.4435419999063015,\"memory\":197.29},{\"round\":4,\"log\":954,\"cpu\":0.0819999985396862,\"memory\":197.34},{\"round\":4,\"log\":955,\"cpu\":5.296812999993563,\"memory\":203.13},{\"round\":4,\"log\":956,\"cpu\":0.14555899985134602,\"memory\":203.29},{\"round\":4,\"log\":957,\"cpu\":5.8728290013968945,\"memory\":196.75},{\"round\":4,\"log\":958,\"cpu\":0.25239899940788746,\"memory\":197.05},{\"round\":4,\"log\":959,\"cpu\":6.172908000648022,\"memory\":203.04},{\"round\":4,\"log\":960,\"cpu\":7.377261999994516,\"memory\":193.2},{\"round\":4,\"log\":961,\"cpu\":6.701104998588562,\"memory\":196.74},{\"round\":4,\"log\":962,\"cpu\":0.21774900145828724,\"memory\":196.87},{\"round\":4,\"log\":963,\"cpu\":0.20769899897277355,\"memory\":197.01},{\"round\":4,\"log\":964,\"cpu\":0.20911899954080582,\"memory\":197.14},{\"round\":4,\"log\":965,\"cpu\":0.2087590005248785,\"memory\":197.29},{\"round\":4,\"log\":966,\"cpu\":0.1893090009689331,\"memory\":197.43},{\"round\":4,\"log\":967,\"cpu\":149.56505700014532,\"memory\":42.6},{\"round\":4,\"log\":968,\"cpu\":0.05847899988293648,\"memory\":42.6},{\"round\":4,\"log\":969,\"cpu\":43.71736499853432,\"memory\":55.16},{\"round\":4,\"log\":970,\"cpu\":0.05048000067472458,\"memory\":55.16}]]"
  },
  {
    "path": "scripts/fakedom/uibench-reactlike/app.js",
    "content": "import { version, Component, render } from 'inferno';\nimport {run, init} from './../libs/uibench.js';\n\ninit('Inferno [same as react]', version, {\n  disableChecks: true,\n  report: true\n});\n\nclass TableCell extends Component {\n  constructor(props) {\n    super(props);\n    this.onClick = this.onClick.bind(this);\n  }\n\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.text !== nextProps.text;\n  }\n\n  onClick(e) {\n    console.log('Clicked' + this.props.text);\n    e.stopPropagation();\n  }\n\n  render() {\n    return (\n      <td className=\"TableCell\" onClick={this.onClick}>\n        {this.props.text}\n      </td>\n    );\n  }\n}\n\nclass TableRow extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const { data } = this.props;\n\n    // Interned strings\n    const classes = data.active ? 'TableRow active' : 'TableRow';\n\n    const cells = data.props;\n\n    const children = [<TableCell key={-1} text={'#' + data.id}></TableCell>];\n    for (let i = 0; i < cells.length; i++) {\n      // Key is used because React prints warnings that there should be a key, libraries that can detect that children\n      // shape isn't changing should render cells without keys.\n      children.push(<TableCell key={i} text={cells[i]}></TableCell>);\n    }\n\n    // First table cell is inserted this way to prevent react from printing warning that it doesn't have key property\n    return (\n      <tr className={classes} data-id={data.id}>\n        {children}\n      </tr>\n    );\n  }\n}\n\nclass Table extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const items = this.props.data.items;\n\n    const children = [];\n    for (let i = 0; i < items.length; i++) {\n      const item = items[i];\n      children.push(<TableRow key={item.id} data={item} />);\n    }\n\n    return (\n      <table className=\"Table\">\n        <tbody>{children}</tbody>\n      </table>\n    );\n  }\n}\n\nclass AnimBox extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const { data } = this.props;\n    const time = data.time;\n    const style = {\n      'border-radius': (time % 10).toString() + 'px',\n      background: 'rgba(0,0,0,' + (0.5 + (time % 10) / 10).toString() + ')'\n    };\n\n    return <div className=\"AnimBox\" data-id={data.id} style={style} />;\n  }\n}\n\nclass Anim extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const items = this.props.data.items;\n\n    const children = [];\n    for (let i = 0; i < items.length; i++) {\n      const item = items[i];\n      children.push(<AnimBox key={item.id} data={item} />);\n    }\n\n    return <div className=\"Anim\">{children}</div>;\n  }\n}\n\nclass TreeLeaf extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    return <li className=\"TreeLeaf\">{this.props.data.id}</li>;\n  }\n}\n\nclass TreeNode extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const { data } = this.props;\n    const children = [];\n\n    for (let i = 0; i < data.children.length; i++) {\n      const n = data.children[i];\n      if (n.container) {\n        children.push(<TreeNode key={n.id} data={n} />);\n      } else {\n        children.push(<TreeLeaf key={n.id} data={n} />);\n      }\n    }\n\n    return <ul className=\"TreeNode\">{children}</ul>;\n  }\n}\n\nclass Tree extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    return (\n      <div className=\"Tree\">\n        <TreeNode data={this.props.data.root} />\n      </div>\n    );\n  }\n}\n\nclass Main extends Component {\n  shouldComponentUpdate(nextProps, nextState) {\n    return this.props.data !== nextProps.data;\n  }\n\n  render() {\n    const { data } = this.props;\n    const location = data.location;\n\n    var section;\n    if (location === 'table') {\n      section = <Table data={data.table}></Table>;\n    } else if (location === 'anim') {\n      section = <Anim data={data.anim}></Anim>;\n    } else if (location === 'tree') {\n      section = <Tree data={data.tree}></Tree>;\n    }\n\n    return <div className=\"Main\">{section}</div>;\n  }\n}\n\nexport function runUIBench(container, onUpdate) {\n  return new Promise((resolve) => {\n    run(\n      function (state) {\n        render(<Main data={state} />, container);\n        onUpdate()\n      },\n      resolve,\n      null,\n    );\n  })\n}\n"
  },
  {
    "path": "scripts/fakedom/uibench-reactlike/start.js",
    "content": "import {writeFile} from 'fs';\nimport {container} from '../libs/setup.js';\nimport {runUIBench} from './dist/bundle.js'\nimport CliTable from 'cli-table';\nimport Table from 'cli-table';\nconsole.log(\"Sanity check starts\")\n\n// const perfData = [];\n// const totalAllocations = [];\n//\n// function collectAllocations(node) {\n//   let currentNode;\n//   let totalEverything = 0;\n//   let totalOwn  = 0;\n//   const allocations = []\n//   const stack = [node];\n//\n//   while ((currentNode = stack.pop()) !== undefined) {\n//     stack.push(...currentNode.children)\n//\n//     totalEverything += currentNode.selfSize;\n//\n//     if (currentNode.selfSize > 0 && currentNode.callFrame.url.endsWith('bundle.js')) {\n//       totalOwn += currentNode.selfSize;\n//       allocations.push({\n//         method: currentNode.callFrame.functionName,\n//         size: currentNode.selfSize\n//       })\n//     }\n//   }\n//\n//   return {\n//     totalEverything,\n//     totalOwn,\n//     allocations: allocations.sort((a, b) => a.size - b.size).slice(0, 10)\n//   };\n// }\n\nconst formatMemoryUsage = (data) => Math.round(data / 1024 / 1024 * 100) / 100;\n\n\nglobal.gc();\nconst allStats = [];\n\n\nfor (let i = 0; i < 5; i++) {\n  const statistics = [];\n  let log = 0;\n\n  global.gc();\n\n  let startHeap = process.memoryUsage().heapUsed;\n  let startTime = performance.now();\n\n  await runUIBench(container, () => {\n    const perfNowEnds = performance.now();\n    const endHeap = process.memoryUsage().heapUsed;\n\n    // console.log( \"iter => \" + i + \" Sanity check ends memory\");\n    const cpu = perfNowEnds - startTime;\n    const memory = endHeap - startHeap;\n    startTime = perfNowEnds\n    statistics.push({\n      round: i,\n      log: log++,\n      cpu,\n      memory: formatMemoryUsage(memory)\n    })\n  });\n\n\n\n  // const memory = collectAllocations(heapProfile.head);\n\n\n  allStats.push(statistics);\n  // console.log()\n\n  // console.log(\"CPU \" + cpu + \" Memory \" + formatMemoryUsage(memory),  \" heap used: \" + heapUsed.map(formatMemoryUsage).join(','));\n}\n\n\nlet json = JSON.stringify(allStats);\nwriteFile('./scripts/fakedom/results/inferno_base_line.json', json, (err) => {\n  if (err) {\n    console.err(err);\n  } else {\n    console.log(\"results saved\");\n  }\n});\n\n// printCpuStats(allStats);\n\n\n\n"
  },
  {
    "path": "scripts/fakedom/viewer.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Inferno Examples</title>\n  <script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\n</head>\n\n<div>\n  <canvas id=\"memChart\"></canvas>\n  <canvas id=\"cpuChart\"></canvas>\n</div>\n\n<script>\n  const memChart = document.getElementById('memChart');\n  const cpuChart = document.getElementById('cpuChart');\n\n  function createChart(stats, el, type, scales) {\n\n    const dataSets = [];\n\n    let labels = [];\n    for (let i = 0; i < stats[0].length; i++) {\n      labels.push(i)\n    }\n\n    for (let r = 0; r < stats.length; r++) {\n      const statsRow = stats[r];\n      const dataSet = {\n        label: 'base' + r,\n        data: [],\n        fill: false,\n        borderColor: 'rgb(75, 192, 192)',\n        borderWidth: 1,\n        radius: 0,\n        tension: 0.1\n      }\n\n      for (const testStat of statsRow) {\n        dataSet.data.push(testStat[type])\n      }\n\n      dataSets.push(dataSet)\n    }\n\n    const data = {\n      labels: labels,\n      datasets: dataSets\n    };\n\n    new Chart(el, {\n      type: 'line',\n      data: data,\n      options: {\n        animation: false,\n        responsive: true,\n        plugins: {\n          legend: {\n            position: 'top',\n          },\n          title: {\n            display: true,\n            text: 'Chart.js Line Chart'\n          }\n        },\n        scales\n      },\n    });\n  }\n\n  ;(async function() {\n    const stats = await (await fetch('/scripts/fakedom/results/inferno_base_line.json')).json()\n\n    createChart(stats, memChart, 'memory')\n    createChart(stats, cpuChart, 'cpu', {\n      y: {\n        min: -0.5,\n        max: 30\n      }\n    })\n  }())\n</script>\n<body>\n\n\n\n"
  },
  {
    "path": "scripts/fakedom/viewer.js",
    "content": "import { BarChart, LineChart } from 'chartist';\nimport { readFileSync } from 'fs';\nimport Table from 'cli-table';\n\nconst baseLineStr = readFileSync('./scripts/fakedom/results/inferno_base_line.json').toString();\nconst baseLineJson = JSON.parse(baseLineStr);\n\nfunction buildChartData(stats, name) {\n  let labels = [];\n  for (let i = 0; i < stats.length; i++) {\n    labels.push(`${name} R:${i}`)\n  }\n\n  const table = new Table(head);\n\n  for (let r = 0; r  < stats.length; r++) {\n    const statsRow = stats[r];\n    const tr = [`Round ${r}`]\n\n    for (const testStat of statsRow) {\n      tr.push(testStat.cpu)\n    }\n\n    table.push(tr);\n  }\n\n  console.log(table.toString());\n}\n\nbuildChartData(baseLineJson, 'base');\n\nnew LineChart('.ct-chart', {\n  labels: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],\n  series: [\n    [12, 9, 7, 8, 5],\n    [2, 1, 3.5, 7, 3],\n    [1, 3, 4, 5, 6]\n  ]\n}, {\n  fullWidth: true,\n  chartPadding: {\n    right: 40\n  }\n});\n"
  },
  {
    "path": "scripts/rollup/build.js",
    "content": "import fs, { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { join, dirname } from 'path';\n\nimport { createPlugins } from './plugins/index.js';\n\nimport { rollup } from 'rollup';\n\nimport minimist from 'minimist';\n\nconst {\n  promises: { mkdir: mkdirAsync },\n  lstatSync,\n  readdirSync\n} = fs;\n\nconst cwd = process.cwd();\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst ROOT = join(__dirname, '../../packages');\n\nconst pkgJSONtext = readFileSync(join(cwd, 'package.json'));\nconst pkgJSON = JSON.parse(pkgJSONtext);\n\n// Self calling function to allow async/await for readability\n(async () => {\n  if (pkgJSON.private || !pkgJSON.rollup) {\n    return;\n  }\n\n  const args = minimist(process.argv.slice(2));\n\n  const moduleGlobals = readdirSync(ROOT)\n    .filter((path) => lstatSync(join(ROOT, path)).isDirectory())\n    .reduce((acc, pkgName) => {\n      const pkgJSONtext = readFileSync(join(ROOT, pkgName, 'package.json'));\n      const pkgJSON = JSON.parse(pkgJSONtext);\n\n      if (pkgJSON.rollup && pkgJSON.rollup.moduleName) {\n        acc[pkgJSON.name] = pkgJSON.rollup.moduleName;\n      }\n\n      return acc;\n    }, {});\n\n  // Create dist folder\n  await mkdirAsync(join(cwd, 'dist')).catch((err) => {\n    if (err.code !== 'EEXIST') {\n      throw Error(err);\n    }\n  });\n\n  // Get info from package.json\n  const { version, rollup: rollupConfig = {}, dependencies = {}, devDependencies = {}, peerDependencies = {} } = pkgJSON;\n\n  // Figure out from package.json what dependencies to bundle\n  function exclusionFilter(name) {\n    return !(rollupConfig.bundledDependencies || []).includes(name);\n  }\n\n  const deps = Object.assign({}, devDependencies, peerDependencies, dependencies);\n  const external = Object.keys(deps)\n    .filter(exclusionFilter)\n    .filter(function (elem, index, self) {\n      return index === self.indexOf(elem);\n    });\n\n  // The import stream is NodeJS specific and should alwats be marked as external\n  // Used in inferno-server\n  external.push('stream');\n\n  const defaultOptions = {\n    name: 'index',\n    replace: true,\n    version: pkgJSON.version\n  };\n\n  const targets = [\n    //esmDev --name=index --ext=.dev.esm.js --env=development --format=es --minify=false\n    Object.assign({}, defaultOptions, { env: 'development', format: 'es', esnext: true, minify: false, ext: '.dev.mjs' }),\n    //esmProd --name=index --ext=.esm.js --env=production --format=es --minify=false\n    Object.assign({}, defaultOptions, { env: 'production', format: 'es', esnext: true, minify: false, ext: '.mjs' }),\n    //cjsDev --env=development --format=cjs --replace=true --name=index.cjs --minify=false\n    Object.assign({}, defaultOptions, { env: 'development', format: 'cjs', minify: false, ext: '.cjs' }),\n    //cjsProd --env=production --format=cjs --replace=true --name=index.cjs --minify=true --ext=.min.js\n    Object.assign({}, defaultOptions, { env: 'production', format: 'cjs', minify: true, ext: '.min.cjs' }),\n    //umdDev --minify=false\n    Object.assign({}, defaultOptions, {\n      env: 'development',\n      format: 'umd',\n      minify: false,\n      name: pkgJSON.name,\n      ext: '.js'\n    }),\n    //umdProd --env=production --ext=.min.js\n    Object.assign({}, defaultOptions, {\n      env: 'production',\n      format: 'umd',\n      minify: true,\n      name: pkgJSON.name,\n      ext: '.min.js'\n    })\n  ].filter((target) => {\n    if (args['target-ext']) {\n      return target.ext === args['target-ext'];\n    }\n    return true;\n  });\n\n  async function startBuilding(options) {\n    const errorFunc = (error) => {\n      console.error(error); // Print whole error object\n\n      if (error.snippet) {\n        console.error('\\u001b[31;1m');\n        console.error('\\n-------- Details -------');\n        console.error(error.id);\n        console.error(error.loc);\n        console.error('\\n-------- Snippet --------');\n        console.error(error.snippet);\n        console.error('\\n-------------------------');\n        console.error('\\u001b[0m');\n      }\n\n      console.error(`${pkgJSON.name} in ${options.format} is FAILED ${error.message}`);\n      process.exit(-1); // Do not continue build in case of error to avoid publishing garbage, Github #1157\n    };\n\n    // Minify settings are found in plugins/index.js\n    const rollupPlugins = createPlugins(version, options);\n\n    // Transform\n    const { write } = await rollup({\n      input: join(cwd, 'tmpDist/index.js'),\n      external: external,\n      plugins: rollupPlugins\n    }).catch(errorFunc);\n\n    // Write bundle\n    const filename = `${options.name}${options.ext}`;\n\n    // TODO: Consider adding globals to avoid warnings:\n    // No name was provided for external module 'stream' in output.globals – guessing 'stream'\n    // No name was provided for external module 'history' in output.globals – guessing 'history'\n    // No name was provided for external module 'path-to-regexp-es6' in output.globals – guessing 'pathToRegexp'\n    // No name was provided for external module 'hoist-non-inferno-statics' in output.globals – guessing 'hoistNonReactStatics'\n    // No name was provided for external module 'redux' in output.globals – guessing 'redux'\n    // No name was provided for external module 'mobx' in output.globals – guessing 'mobx'\n\n    const outputOptions = {\n      file: `dist/${filename}`,\n      format: options.format,\n      globals: Object.assign(moduleGlobals, rollupConfig.moduleGlobals),\n      name: rollupConfig.moduleName,\n      indent: true,\n      extend: true,\n      sourcemap: false\n    };\n\n    if (options.format === 'cjs') {\n      outputOptions.exports = 'named';\n    }\n\n    await write(outputOptions).catch(errorFunc);\n    console.log(`${pkgJSON.name} in ${options.name}${options.ext} is DONE`);\n  }\n\n  await Promise.all(targets.map(startBuilding));\n})();\n"
  },
  {
    "path": "scripts/rollup/plugins/alias.js",
    "content": "import { dirname, join, resolve } from 'path';\n\nimport alias from '@rollup/plugin-alias';\nimport { fileURLToPath } from 'url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst ROOT = join(__dirname, '../../../');\n\nexport const aliasPlugin = alias({\n  resolve: ['.js'],\n  entries: [\n    { find: 'inferno', replacement: resolve(ROOT, 'packages/inferno/tmpDist/index.js') },\n    { find: 'inferno-animation', replacement: resolve(ROOT, 'packages/inferno-animation/tmpDist/index.js') },\n    { find: 'inferno-compat', replacement: resolve(ROOT, 'packages/inferno-compat/tmpDist/index.js') },\n    { find: 'inferno-create-element', replacement: resolve(ROOT, 'packages/inferno-create-element/tmpDist/index.js') },\n    { find: 'inferno-hyperscript', replacement: resolve(ROOT, 'packages/inferno-hyperscript/tmpDist/index.js') },\n    { find: 'inferno-mobx', replacement: resolve(ROOT, 'packages/inferno-mobx/tmpDist/index.js') },\n    { find: 'inferno-redux', replacement: resolve(ROOT, 'packages/inferno-redux/tmpDist/index.js') },\n    { find: 'inferno-router', replacement: resolve(ROOT, 'packages/inferno-router/tmpDist/index.js') },\n    { find: 'inferno-server', replacement: resolve(ROOT, 'packages/inferno-server/tmpDist/index.js') },\n    { find: 'inferno-shared', replacement: resolve(ROOT, 'packages/inferno-shared/tmpDist/index.js') },\n    { find: 'inferno-clone-vnode', replacement: resolve(ROOT, 'packages/inferno-clone-vnode/tmpDist/index.js') },\n    { find: 'inferno-hydrate', replacement: resolve(ROOT, 'packages/inferno-hydrate/tmpDist/index.js') }\n  ]\n});\n"
  },
  {
    "path": "scripts/rollup/plugins/index.js",
    "content": "import commonjs from '@rollup/plugin-commonjs';\nimport nodeResolve from '@rollup/plugin-node-resolve';\nimport replacePlugin from '@rollup/plugin-replace';\nimport terser from '@rollup/plugin-terser';\nimport { aliasPlugin } from './alias.js';\nimport babel from '@rollup/plugin-babel';\n\nexport function createPlugins(version, options) {\n  const plugins = [\n    aliasPlugin,\n    nodeResolve({\n      extensions: ['.js', '.json'],\n      mainFields: ['module', 'main'],\n      preferBuiltins: true\n    }),\n    commonjs({\n      include: 'node_modules/**'\n    })\n  ];\n\n  plugins.push(\n    babel({\n      exclude: 'node_modules/**',\n      sourceMaps: false,\n      babelrc: false,\n      presets: !options.esnext ? [['@babel/env', { loose: true, modules: false }]] : null,\n      babelHelpers: 'runtime',\n      skipPreflightCheck: true,\n      plugins: [['@babel/plugin-proposal-class-properties', { loose: true }]]\n    })\n  );\n\n  const replaceValues = {\n    preventAssignment: true,\n    'process.env.INFERNO_VERSION': JSON.stringify(options.version)\n  };\n\n  if (options.replace) {\n    replaceValues['process.env.NODE_ENV'] = JSON.stringify(options.env);\n  }\n\n  plugins.push(replacePlugin(replaceValues));\n\n  if (options.minify) {\n    plugins.push(\n      terser({\n        compress: {\n          ecma: 5,\n          inline: true,\n          if_return: false,\n          reduce_funcs: false,\n          passes: 5,\n          comparisons: false\n        },\n        ie8: false,\n        mangle: {\n          toplevel: true\n        },\n        parse: {\n          html5_comments: false,\n          shebang: false\n        },\n        toplevel: false,\n        warnings: false\n      })\n    );\n  }\n\n  return plugins;\n}\n"
  },
  {
    "path": "scripts/test/globals.js",
    "content": "var usingJest = false;\n"
  },
  {
    "path": "scripts/test/jasmine-polyfill.js",
    "content": "global.it.skip = xit;\nglobal.it.only = fit;\nglobal.describe.skip = xdescribe;\nglobal.describe.only = fdescribe;\n"
  },
  {
    "path": "scripts/test/requestAnimationFrame.ts",
    "content": "// 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(function () {\n  let lastTime = 0;\n  const vendors = ['ms', 'moz', 'webkit', 'o'];\n\n  for (let x = 0; x < vendors.length && !global.requestAnimationFrame; ++x) {\n    global.requestAnimationFrame = global[vendors[x] + 'RequestAnimationFrame'];\n    global.cancelAnimationFrame =\n      global[vendors[x] + 'CancelAnimationFrame'] || global[vendors[x] + 'CancelRequestAnimationFrame'];\n  }\n\n  if (!global.requestAnimationFrame) {\n    global.requestAnimationFrame = function (callback): number {\n      const currTime = new Date().getTime();\n      const timeToCall = Math.max(0, 16 - (currTime - lastTime));\n      const id = global.setTimeout(function () {\n        callback(currTime + timeToCall);\n      }, timeToCall);\n      lastTime = currTime + timeToCall;\n      return id as unknown as number;\n    };\n  }\n\n  if (!global.cancelAnimationFrame) {\n    global.cancelAnimationFrame = function (id) {\n      clearTimeout(id);\n    };\n  }\n})();\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"inferno\": [\n        \"packages/inferno/src/index.ts\"\n      ],\n      \"inferno-compat\": [\n        \"packages/inferno-compat/src/index.ts\"\n      ],\n      \"inferno-animation\": [\n        \"packages/inferno-animation/src/index.ts\"\n      ],\n      \"inferno-create-element\": [\n        \"packages/inferno-create-element/src/index.ts\"\n      ],\n      \"inferno-hydrate\": [\n        \"packages/inferno-hydrate/src/index.ts\"\n      ],\n      \"inferno-extras\": [\n        \"packages/inferno-extras/src/index.ts\"\n      ],\n      \"inferno-hyperscript\": [\n        \"packages/inferno-hyperscript/src/index.ts\"\n      ],\n      \"inferno-mobx\": [\n        \"packages/inferno-mobx/src/index.ts\"\n      ],\n      \"inferno-redux\": [\n        \"packages/inferno-redux/src/index.ts\"\n      ],\n      \"inferno-router\": [\n        \"packages/inferno-router/src/index.ts\"\n      ],\n      \"inferno-server\": [\n        \"packages/inferno-server/src/index.ts\"\n      ],\n      \"inferno-shared\": [\n        \"packages/inferno-shared/src/index.ts\"\n      ],\n      \"inferno-clone-vnode\": [\n        \"packages/inferno-clone-vnode/src/index.ts\"\n      ],\n      \"inferno-test-utils\": [\n        \"packages/inferno-test-utils/src/index.ts\"\n      ],\n      \"inferno-utils\": [\n        \"packages/inferno-utils/src/index.ts\"\n      ],\n      \"inferno-vnode-flags\": [\n        \"packages/inferno-vnode-flags/src/index.ts\"\n      ],\n      \"mobx\": [\n        \"node_modules/mobx/dist/mobx.esm.js\"\n      ]\n    },\n    \"newLine\": \"LF\",\n    \"noUnusedParameters\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"declaration\": true,\n    \"target\": \"es2022\",\n    \"lib\": [\"DOM\", \"ES2022\"],\n    \"module\": \"esnext\",\n    \"allowJs\": false,\n    \"moduleResolution\": \"node\",\n    \"preserveConstEnums\": true,\n    \"outDir\": \"build\",\n    \"sourceMap\": true,\n    \"jsx\": \"preserve\",\n    \"jsxFactory\": \"Inferno.createElement\",\n    \"jsxFragmentFactory\": \"Fragment\",\n    \"noUnusedLocals\": true,\n    \"noImplicitReturns\": true,\n    \"alwaysStrict\": true,\n    \"strictNullChecks\": true,\n    \"strictFunctionTypes\": true,\n    \"removeComments\": false,\n    \"experimentalDecorators\": false,\n    \"rootDir\": \".\"\n  },\n  \"include\": [\n    \"packages/*/src\",\n    \"packages/*/__tests__\"\n  ]\n}\n"
  }
]