[
  {
    "path": ".editorconfig",
    "content": "# EditorConfig is awesome: http://EditorConfig.org\n\n# top-most EditorConfig file\nroot = true\n\n# Unix-style newlines with a newline ending every file\n[*]\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 2\ntrim_trailing_whitespace = true\n\n[*.gradle]\nindent_size = 4\n"
  },
  {
    "path": ".eslintignore",
    "content": "node_modules\nlib\nes\ndist\nbuild\ncoverage\nexpected\nwebsite\ngh-pages\nvendors\n"
  },
  {
    "path": ".eslintrc.js",
    "content": "module.exports = {\n  'extends': [\n    'rax'\n  ],\n  'root': true,\n};\n"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "# Contributing Guide\n\nHi! I’m really excited that you are interested in contributing to Rax. Before submitting your contribution though, please make sure to take a moment and read through the following guidelines.\n\n- [Issue Reporting Guidelines](#issue-reporting-guidelines)\n- [Pull Request Guidelines](#pull-request-guidelines)\n- [Git Commit Specific](./GIT_COMMIT_SPECIFIC.md)\n\n## Development Workflow\n\nAfter cloning rax, run `npm install` to fetch its dependencies.  \nRun `npm run setup` link and bootstrap project before development.\nThen, you can run several commands:\n\n* `npm run lint` checks the code style.\n* `npm test` runs the complete test suite.\n* `npm test -- --watch` runs an interactive test watcher.\n* `npm test <pattern>` runs tests with matching filenames.\n* `npm run build` creates `lib` and `dist` folder with all the packages.\n\n## Issue Reporting Guidelines\n\n- The issue list of this repo is **exclusively** for bug reports and feature requests. Non-conforming issues will be closed immediately.\n\n  - For simple beginner questions, you can get quick answers from\n\n  - For more complicated questions, you can use Google or StackOverflow. Make sure to provide enough information when asking your questions - this makes it easier for others to help you!\n\n- Try to search for your issue, it may have already been answered or even fixed in the development branch.\n\n- Check if the issue is reproducible with the latest stable version of Rax. If you are using a pre-release, please indicate the specific version you are using.\n\n- It is **required** that you clearly describe the steps necessary to reproduce the issue you are running into. Issues with no clear repro steps will not be triaged. If an issue labeled \"need repro\" receives no further input from the issue author for more than 5 days, it will be closed.\n\n- For bugs that involves build setups, you can create a reproduction repository with steps in the README.\n\n- If your issue is resolved but still open, don’t hesitate to close it. In case you found a solution by yourself, it could be helpful to explain how you fixed it.\n\n## Pull Request Guidelines\n\n- Only code that's ready for release should be committed to the master branch. All development should be done in dedicated branches.\n- Checkout a **new** topic branch from master branch, and merge back against master branch.\n- Work in the `src` folder and **DO NOT** checkin `dist` in the commits.\n- Make sure `npm test` passes.\n- If adding new feature:\n  - Add accompanying test case.\n  - Provide convincing reason to add this feature. Ideally you should open a suggestion issue first and have it greenlighted before working on it.\n- If fixing a bug:\n  - If you are resolving a special issue, add `(fix #xxxx[,#xxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `update entities encoding/decoding (fix #3899)`.\n  - Provide detailed description of the bug in the PR. Live demo preferred.\n  - Add appropriate test coverage if applicable.\n\n\n## Git Commit Specific\n\n- Your commits message must follow our [git commit specific](./GIT_COMMIT_SPECIFIC.md).\n- We will check your commit message, if it does not conform to the specification, the commit will be automatically refused, make sure you have read the specification above.\n- You could use `git cz` with a CLI interface to replace `git commit` command, it will help you to build a proper commit-message, see [commitizen](https://github.com/commitizen/cz-cli).\n- It's OK to have multiple small commits as you work on your branch - we will let GitHub automatically squash it before merging.\n"
  },
  {
    "path": ".github/GIT_COMMIT_SPECIFIC.md",
    "content": "# GIT COMMIT MESSAGE CHEAT SHEET\n\n**Proposed format of the commit message**\n\n```\n<type>(<scope>): <subject>\n\n<body>\n```\n\nAll lines are wrapped at 100 characters !\n\n\n**Allowed `<type>`**\n\n- feat (A new feature)\n- fix (A bug fix)\n- docs (Documentation only changes)\n- style (Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc))\n- perf (A code change that improves performance)\n- refactor (A code change that neither fixes a bug nor adds a feature)\n- test (Adding missing tests or correcting existing tests)\n- build (Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm))\n- ci (Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs))\n- chore (Other changes that don't modify src or test files)\n- revert (Reverts a previous commit)\n\n**Allowed `<scope>`**\nScope could be anything specifying place of the commit change.\n\nFor example $location, $browser, compiler, scope, ng:href, etc...\n\n\n**Breaking changes**\nAll breaking changes have to be mentioned in message body, on separated line:\n​\t_Breaks removed $browser.setUrl() method (use $browser.url(newUrl))_\n​\t_Breaks ng: repeat option is no longer supported on selects (use ng:options)_\n\n\n**Message body**\n\n- uses the imperative, present tense: “change” not “changed” nor “changes”\n- includes motivation for the change and contrasts with previous behavior\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "content": "name: \"Bug Report\"\ndescription: \"If something isn't working as expected.\"\ntitle: \"[BUG] <title>\"\nlabels: [\"Bug\"]\nbody:\n  - type: markdown\n    attributes:\n      value: Thanks for taking the time to file a bug report! ❤️ Please fill out this form to describe your issue.\n\n  - type: checkboxes\n    id: input1\n    attributes:\n      label: \"⌨️\"\n      options:\n        - label: Would you like to work on a fix?\n\n  - type: dropdown\n    attributes:\n      label: Where is the bug from?\n      options:\n        - Rax Core\n        - Rax App\n        - Rax Components\n        - Rax Hooks\n        - Uni API\n        - Fusion Mobile\n        - Others\n        - I don't know\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Minimal code and steps to reproduce the bug\n      description: |\n        To help fixing the bug sooner, you should provide the minimal code and steps necessary to reproduce the bug.\n        Even better, you can share us a CodeSandbox link. [Create a new codesandbox](https://codesandbox.io/s/rax-quick-start-smqdc?file=/build.json&resolutionWidth=375&resolutionHeight=812).\n        If it's not possible to reproduce the bug with simple code, a GitHub repository link is also ok.\n      placeholder: |\n        ```js\n        const your => (code) => here;\n        ```\n        1. In this environment...\n        2. With this config...\n        3. Run '...'\n        4. See error...\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Current and expected behavior\n      description: A clear and concise description of what it happens and what you would expect.\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Environment\n      placeholder: |\n        - OS: [e.g. macOS 10.15.4, Windows 10, iOS]\n        - Rax version: [e.g. 1.2.2]\n        - Rax App version: [e.g. 3.8.0]\n        - Node: [e.g. Node 15]\n        - Browser: [e.g. chrome, safari]\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: build.json\n      description: |\n        If there is a build config file(e.g. build.json) in your project, paste its content here\n      placeholder: |\n        ```json\n        {\n          \"your\": { \"config\": \"here\" }\n        }\n        ```\n\n  - type: textarea\n    attributes:\n      label: Possible solution\n      description: \"If you have any suggestion on a fix for the bug.\"\n\n  - type: textarea\n    attributes:\n      label: Additional context\n      description: \"Add any other context about the problem here. Or a screenshot if applicable.\""
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "content": "---\nname: Feature Request\nabout: Suggest an idea for Rax.\ntitle: \"[Feature]\"\nlabels: feature\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "content": "---\nname: Question\nabout: Ask questions about using with Rax.\ntitle: \"[Question]\"\nlabels: question\nassignees: ''\n\n---\n\nPlease describe the problem you meet.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "*Before* submitting a pull request, please make sure the following is done...\n\n1. Fork the repo and create your branch from `master`.\n2. If you've added code that should be tested, add tests!\n3. If you've changed APIs, update the documentation.\n4. Ensure the test suite passes (`npm test`).\n5. Make sure your code lints (`npm run lint`) - we've done our best to make sure these rules match our internal linting guidelines.\n"
  },
  {
    "path": ".github/actions/setup-chrome/action.yml",
    "content": "# https://github.com/SeleniumHQ/selenium/blob/trunk/.github/actions/setup-chrome/action.yml\nname: 'Setup Chrome and chromedriver'\nruns:\n  using: \"composite\"\n  steps:\n    - run: |\n        wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -\n        echo \"deb http://dl.google.com/linux/chrome/deb/ stable main\" | sudo tee -a /etc/apt/sources.list.d/google-chrome.list\n        sudo apt-get update -qqy\n        sudo apt-get -qqy install google-chrome-stable\n        CHROME_VERSION=$(google-chrome-stable --version)\n        CHROME_FULL_VERSION=${CHROME_VERSION%%.*}\n        CHROME_MAJOR_VERSION=${CHROME_FULL_VERSION//[!0-9]}\n        sudo rm /etc/apt/sources.list.d/google-chrome.list\n        export CHROMEDRIVER_VERSION=`curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE_${CHROME_MAJOR_VERSION%%.*}`\n        curl -L -O \"https://chromedriver.storage.googleapis.com/${CHROMEDRIVER_VERSION}/chromedriver_linux64.zip\"\n        unzip chromedriver_linux64.zip && chmod +x chromedriver && sudo mv chromedriver /usr/local/bin\n        export CHROMEDRIVER_VERSION=`curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE_${CHROME_MAJOR_VERSION%%.*}`\n        curl -L -O \"https://chromedriver.storage.googleapis.com/${CHROMEDRIVER_VERSION}/chromedriver_linux64.zip\"\n        unzip chromedriver_linux64.zip && chmod +x chromedriver && sudo mv chromedriver /usr/local/bin\n        chromedriver -version\n      shell: bash\n"
  },
  {
    "path": ".github/workflows/auto-publisher.yml",
    "content": "name: Auto Publisher\n\non:\n  push:\n    branches:\n      - master\n\njobs:\n  build-and-publish:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v1\n      - uses: actions/setup-node@v1\n        with:\n          node-version: 14\n          registry-url: https://registry.npmjs.org/\n      - run: npm install\n      - run: npm run setup\n      - run: npm run check-and-publish\n        env:\n          NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}\n          ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }}\n          ACCESS_KEY_SECRET: ${{ secrets.ACCESS_KEY_SECRET }}\n          REGISTRY: https://registry.npmjs.org\n"
  },
  {
    "path": ".github/workflows/bench.yml",
    "content": "name: Bench\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - '^bench'\n\njobs:\n  bench:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v1\n      - uses: actions/setup-node@v1\n        with:\n          node-version: 14\n          registry-url: https://registry.npmjs.org/\n      - name: Setup Chrome and chromedriver\n        uses: ./.github/actions/setup-chrome\n      - name: Start XVFB\n        run: Xvfb :99 &\n      - run: npm install\n      - run: npm run setup\n      - run: npm run bench\n        env:\n          DISPLAY: :99\n          ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }}\n          ACCESS_KEY_SECRET: ${{ secrets.ACCESS_KEY_SECRET }}\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non: [push]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        node-version: [14.x]\n    steps:\n    - uses: actions/checkout@v2\n    - name: Set branch name\n      run: echo >>$GITHUB_ENV BRANCH_NAME=${GITHUB_REF#refs/heads/}\n    - name: Echo branch name\n      run: echo ${BRANCH_NAME}\n    - name: Use Node.js ${{ matrix.node-version }}\n      uses: actions/setup-node@v1\n      with:\n        node-version: ${{ matrix.node-version }}\n        registry-url: https://registry.npmjs.org/\n    - run: npm run setup\n    - run: npm run lint\n    - run: npm run test\n      env:\n        ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }}\n        ACCESS_KEY_SECRET: ${{ secrets.ACCESS_KEY_SECRET }}\n        CI: true\n"
  },
  {
    "path": ".gitignore",
    "content": "*~\n*.swp\n.DS_Store\nnpm-debug.log\nlerna-debug.log\nnpm-debug.log*\nlib/\nes/\ndist/\nbuild/\ncoverage/\nnode_modules/\nexamples/test\n.eslintcache\n*.lock\n"
  },
  {
    "path": ".npmrc",
    "content": "package-lock=false"
  },
  {
    "path": "LICENSE",
    "content": "BSD License\n\nCopyright (c) 2015-present, Alibaba Group Holding Limited. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n\n * Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\n * Neither the name of the copyright holder nor the names of its contributors may be used to\n   endorse or promote products derived from this software without specific\n   prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <a href=\"https://alibaba.github.io/rax\">\n    <img alt=\"Rax\" src=\"https://user-images.githubusercontent.com/677114/59907138-e99f7180-943c-11e9-8769-07021d9fe1ca.png\" width=\"66\">\n  </a>\n</p>\n\n<p align=\"center\">\nRax is a progressive framework for building universal applications.\n\n<p align=\"center\">\n  <a href=\"https://github.com/alibaba/rax/blob/master/LICENSE\"><img src=\"https://img.shields.io/npm/l/rax.svg\"></a>\n  <a href=\"https://www.npmjs.com/package/rax\"><img src=\"https://img.shields.io/npm/v/rax.svg\"></a>\n  <a href=\"https://www.npmjs.com/package/rax\"><img src=\"https://img.shields.io/npm/dm/rax.svg\"></a>\n  <a href=\"https://travis-ci.org/alibaba/rax\"><img src=\"https://travis-ci.org/alibaba/rax.svg?branch=master\"></a>\n  <a href=\"https://unpkg.com/rax/dist/rax.min.js\"><img src=\"https://img.badgesize.io/https://unpkg.com/rax/dist/rax.min.js?compression=gzip&?maxAge=3600\" alt=\"gzip size\"></a>\n</p>\n\n---\n\n💌 **Write Once, Run Anywhere:** write one codebase, run with `Web`, [`Weex`](https://weex.apache.org/), [`Node.js`](https://nodejs.org/), `Alibaba MiniApp`, and `WeChat MiniProgram`. Rax can be used with additional containers that implement it's [driver specification](https://github.com/alibaba/rax/wiki/Driver-Specification).\n\n⏱ **Fast:** better performance and a tiny size(📦~6KB) when compared to [React](http://reactjs.org/) using the same API.\n\n📤 **Easy:** quick start with zero configuration, all features like `Progressive Web App (PWA)`, `Server-Side Rendering (SSR)`, and `Function as a service (FaaS)` can be used out of the box.\n\n### Quick Start 🥢🍚\n\n#### Start from command line\n\nCreate a new Rax project using `create-rax`:\n\n```sh\n$ npm init rax <YourProjectName>\n```\n_`npm init <initializer>` is available in npm 6+_\n\nStart local server to launch project:\n\n```sh\n$ cd <YourProjectName>\n$ npm install\n$ npm run start\n```\n\n#### Start from [VS Code](https://code.visualstudio.com/)\n\nYou need to install the [AppWorks Pack](https://marketplace.visualstudio.com/items?itemName=iceworks-team.iceworks) and invoke the `Create Application` command from the VS Code command palette (`Ctrl + Shift + P` or `Cmd + Shift + P` on Mac):\n\n![vscode](https://img.alicdn.com/imgextra/i4/O1CN01B2NdUc1LVH9UffWpV_!!6000000001304-1-tps-960-720.gif)\n\n### Developer Tools 🛠\n\nYou can inspect and modify the state of your Rax components at runtime using the\n[Rax Developer Tools](https://github.com/raxjs/rax-devtools) browser extension,\nhowever the extension will not work in `production` mode.\n\n1. Install the Chrome [Rax Developer Tools](https://chrome.google.com/webstore/detail/rax-developer-tools/anpeoinhjjligmgoiepbnigjhmijblff) extension\n2. Reload and go to the 'Rax' tab in the browser's development tools\n\n#### VS Code Extension\n\nYou can use [AppWorks Pack](https://marketplace.visualstudio.com/items?itemName=iceworks-team.iceworks) to get better development experience.\n\n### Awesome Things 📝\n\nYou can find some awesome things in [awesome-rax](https://github.com/raxjs/awesome-rax).\n\n### Contributing 🧼\n\nWant to file a bug, contribute some code, or improve documentation? Excellent! Read up on our [guidelines for contributing](./.github/CONTRIBUTING.md).\n\n#### Code Contributors\n\nThis project exists thanks to all the people who contribute.\n<a href=\"https://github.com/alibaba/rax/graphs/contributors\"><img src=\"https://opencollective.com/rax/contributors.svg?width=890&button=false\" /></a>\n\n### Community support\n\nFor general help using Rax, please refer to [the official site](https://rax.js.org/). For additional help, you can use one of these channels to ask a question:\n\n- [GitHub](https://github.com/alibaba/rax) (Bug reports, contributions)\n- [Twitter](https://twitter.com/RaxNews) (Get the news fast)\n- [Medium](https://medium.com/@raxjs) (Get blogs and articles)\n- [知乎专栏](https://zhuanlan.zhihu.com/raxjs) (Get blogs and articles in Simplified Chinese)\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Supported Versions\n\n\n| Version | Supported          |\n| ------- | ------------------ |\n| >= 1.0.0   | :white_check_mark: |\n| < 1.0.0   | :x:                |\n\n## Reporting a Vulnerability\n\nIf you have any problems, report it to rax-public@alibaba-inc.com, thank you.\n"
  },
  {
    "path": "babel.config.js",
    "content": "module.exports = function(api) {\n  // Cache the returned value forever and don't call this function again.\n  if (api) api.cache(true);\n\n  return {\n    'presets': [\n      '@babel/preset-flow',\n      ['@babel/preset-env', {\n        'loose': true,\n        'targets': {\n          'esmodules': true\n        }\n      }],\n      ['@babel/preset-react', {\n        'pragma': 'createElement'\n      }]\n    ],\n    'plugins': [\n      '@babel/plugin-proposal-export-default-from',\n      [\n        '@babel/plugin-proposal-class-properties',\n        {\n          loose: true\n        }\n      ],\n      'babel-plugin-transform-jsx-stylesheet',\n      [\n        '@babel/plugin-proposal-decorators',\n        {\n          decoratorsBeforeExport: true\n        }\n      ],\n      '@babel/plugin-syntax-dynamic-import',\n    ],\n    'ignore': [\n      'src/generator/templates',\n      '__mockc__',\n      'dist'\n    ],\n  };\n};\n"
  },
  {
    "path": "examples/README.md",
    "content": "# Rax 示例\n\n本文件夹提供了多个 Rax 示例项目供用户参考。\n\n## 快速开始\n\n```shell\nnpm install\n\n# dev mode\nnpm run start\n\n# build mode\nnpm run build\n```\n\n## 示例说明\n\n> 示例项目中小程序端均采用运行时方案\n\n* with-miniapp-native-custom-component: 使用小程序原生自定义组件（本地组件 + npm 组件）\n* with-miniapp-plugin-component: 使用小程序插件组件 + 分端构建\n* with-miniapp-native-page: 使用原生页面\n* use-rax-compiled-component-in-runtime-miniapp: Rax 小程序运行时项目使用 Rax 编译时组件\n* app-lifecycle: 使用 app 生命周期\n* page-lifecycle-with-router: 使用 page 生命周期 + 路由跳转\n* event-handler: 事件绑定（编译时小程序）\n* get-element: document/element getElementXXX 相关 API\n"
  },
  {
    "path": "examples/app-lifecycle/.eslintrc.js",
    "content": "module.exports = {\n  extends: ['rax']\n};"
  },
  {
    "path": "examples/app-lifecycle/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n*~\n*.swp\n*.log\n\n.DS_Store\n.idea/\n.temp/\n\nbuild/\ndist/\nlib/\ncoverage/\nnode_modules/\n\ntemplate.yml\n"
  },
  {
    "path": "examples/app-lifecycle/README.md",
    "content": "# rax-materials-basic-app\n\n## Getting Started\n\n### `npm run start`\n\nRuns the app in development mode.\n\nOpen [http://localhost:9999](http://localhost:9999) to view it in the browser.\n\nThe page will reload if you make edits.\n\n### `npm run build`\n\nBuilds the app for production to the `build` folder.\n"
  },
  {
    "path": "examples/app-lifecycle/build.json",
    "content": "{\n  \"inlineStyle\": false,\n  \"plugins\": [\n    [\n      \"build-plugin-rax-app\",\n      {\n        \"targets\": [\n          \"miniapp\",\n          \"wechat-miniprogram\"\n        ],\n        \"miniapp\": {\n          \"buildType\": \"runtime\"\n        },\n        \"wechat-miniprogram\": {\n          \"buildType\": \"runtime\"\n        }\n      }\n    ]\n  ]\n}\n"
  },
  {
    "path": "examples/app-lifecycle/package.json",
    "content": "{\n  \"name\": \"@rax-materials/scaffolds-app-js\",\n  \"author\": \"rax\",\n  \"description\": \"Rax 无线跨端应用工程，使用 JavaScript。\",\n  \"version\": \"0.1.0\",\n  \"scripts\": {\n    \"build\": \"build-scripts build\",\n    \"start\": \"build-scripts start\",\n    \"lint\": \"eslint --ext .js --ext .jsx ./\"\n  },\n  \"dependencies\": {\n    \"rax\": \"^1.1.0\",\n    \"rax-app\": \"^2.0.0\",\n    \"driver-universal\": \"^3.0.0\",\n    \"rax-image\": \"^2.0.0\",\n    \"rax-link\": \"^1.0.1\",\n    \"rax-text\": \"^1.0.0\",\n    \"rax-view\": \"^1.0.0\",\n    \"rax-document\": \"^0.1.0\"\n  },\n  \"devDependencies\": {\n    \"@alib/build-scripts\": \"^0.1.0\",\n    \"babel-eslint\": \"^10.0.3\",\n    \"build-plugin-rax-app\": \"^5.0.0\",\n    \"eslint\": \"^6.8.0\",\n    \"eslint-config-rax\": \"^0.1.0\",\n    \"eslint-plugin-import\": \"^2.20.0\",\n    \"eslint-plugin-module\": \"^0.1.0\",\n    \"eslint-plugin-react\": \"^7.18.0\"\n  },\n  \"private\": true,\n  \"originTemplate\": \"@rax-materials/scaffolds-app-js\"\n}\n"
  },
  {
    "path": "examples/app-lifecycle/src/app.js",
    "content": "import { runApp, useAppLaunch, useAppShow, useAppHide, useAppShare, useAppError } from 'rax-app';\nimport appConfig from './app.json';\n\nuseAppLaunch((options) => {\n  console.log('app launch', options);\n});\n\nuseAppShow((options) => {\n  console.log('app show', options);\n});\n\nuseAppHide(() => {\n  console.log('app hide');\n});\n\nuseAppShare(() => {\n  return {\n    title: '分享标题',\n    desc: '分享详细说明',\n    path: 'pages/Home/index'\n  };\n});\n\nuseAppError(() => {\n  console.log('app error');\n});\n\nrunApp(appConfig);\n"
  },
  {
    "path": "examples/app-lifecycle/src/app.json",
    "content": "{\n  \"routes\": [\n    {\n      \"path\": \"/\",\n      \"source\": \"pages/Home/index\"\n    }\n  ],\n  \"window\": {\n    \"title\": \"Rax App\"\n  }\n}\n"
  },
  {
    "path": "examples/app-lifecycle/src/components/Logo/index.css",
    "content": ".logo {\n  width: 200rpx;\n  height: 180rpx;\n  margin-bottom: 20rpx;\n}"
  },
  {
    "path": "examples/app-lifecycle/src/components/Logo/index.jsx",
    "content": "import { createElement } from 'rax';\nimport Image from 'rax-image';\n\nimport './index.css';\n\nexport default (props) => {\n  const { uri } = props;\n  const source = { uri };\n  return (\n    <Image\n      className=\"logo\"\n      source={source}\n    />\n  );\n};\n"
  },
  {
    "path": "examples/app-lifecycle/src/document/index.jsx",
    "content": "import { createElement } from 'rax';\nimport { Root, Style, Script} from 'rax-document';\n\nfunction Document() {\n  return (\n    <html>\n      <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover\" />\n        <title>rax-materials-basic-app</title>\n        <Style />\n      </head>\n      <body>\n        {/* root container */}\n        <Root />\n        <Script />\n      </body>\n    </html>\n  );\n}\nexport default Document;\n"
  },
  {
    "path": "examples/app-lifecycle/src/pages/Home/index.css",
    "content": ".home {\n  align-items: center;\n  margin-top: 200rpx;\n}\n\n.title {\n  font-size: 45rpx;\n  font-weight: bold;\n  margin: 20rpx 0;\n}\n\n.info {\n  font-size: 36rpx;\n  margin: 8rpx 0;\n  color: #555;\n}\n"
  },
  {
    "path": "examples/app-lifecycle/src/pages/Home/index.jsx",
    "content": "import { createElement } from 'rax';\nimport View from 'rax-view';\nimport Text from 'rax-text';\n\nimport './index.css';\n\nimport Logo from '../../components/Logo';\n\nexport default function Home() {\n  return (\n    <View className=\"home\">\n      <Logo uri=\"//gw.alicdn.com/tfs/TB1MRC_cvb2gK0jSZK9XXaEgFXa-1701-1535.png\" />\n      <Text className=\"title\">Welcome to Your Rax App</Text>\n      <Text className=\"info\">More information about Rax</Text>\n      <Text className=\"info\">Visit https://rax.js.org</Text>\n    </View>\n  );\n}\n"
  },
  {
    "path": "examples/event-handler/.eslintrc.js",
    "content": "module.exports = {\n  extends: ['rax']\n};"
  },
  {
    "path": "examples/event-handler/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n*~\n*.swp\n*.log\n\n.DS_Store\n.idea/\n.temp/\n\nbuild/\ndist/\nlib/\ncoverage/\nnode_modules/\n\ntemplate.yml\n"
  },
  {
    "path": "examples/event-handler/README.md",
    "content": "# rax-materials-basic-app\n\n## Getting Started\n\n### `npm run start`\n\nRuns the app in development mode.\n\nOpen [http://localhost:9999](http://localhost:9999) to view it in the browser.\n\nThe page will reload if you make edits.\n\n### `npm run build`\n\nBuilds the app for production to the `build` folder.\n"
  },
  {
    "path": "examples/event-handler/build.json",
    "content": "{\n  \"inlineStyle\": false,\n  \"plugins\": [\n    [\n      \"build-plugin-rax-app\",\n      {\n        \"targets\": [\n          \"miniapp\",\n          \"wechat-miniprogram\"\n        ],\n        \"miniapp\": {\n          \"buildType\": \"compile\"\n        },\n        \"wechat-miniprogram\": {\n          \"buildType\": \"compile\"\n        }\n      }\n    ]\n  ]\n}\n"
  },
  {
    "path": "examples/event-handler/package.json",
    "content": "{\n  \"name\": \"@rax-materials/scaffolds-app-js\",\n  \"author\": \"rax\",\n  \"description\": \"Rax 无线跨端应用工程，使用 JavaScript。\",\n  \"version\": \"0.1.0\",\n  \"scripts\": {\n    \"build\": \"build-scripts build\",\n    \"start\": \"build-scripts start\",\n    \"lint\": \"eslint --ext .js --ext .jsx ./\"\n  },\n  \"dependencies\": {\n    \"rax\": \"^1.1.0\",\n    \"rax-app\": \"^2.0.0\",\n    \"driver-universal\": \"^3.0.0\",\n    \"rax-image\": \"^2.0.0\",\n    \"rax-link\": \"^1.0.1\",\n    \"rax-text\": \"^1.0.0\",\n    \"rax-view\": \"^1.0.0\",\n    \"rax-document\": \"^0.1.0\"\n  },\n  \"devDependencies\": {\n    \"@alib/build-scripts\": \"^0.1.0\",\n    \"babel-eslint\": \"^10.0.3\",\n    \"build-plugin-rax-app\": \"^5.0.0\",\n    \"eslint\": \"^6.8.0\",\n    \"eslint-config-rax\": \"^0.1.0\",\n    \"eslint-plugin-import\": \"^2.20.0\",\n    \"eslint-plugin-module\": \"^0.1.0\",\n    \"eslint-plugin-react\": \"^7.18.0\"\n  },\n  \"private\": true,\n  \"originTemplate\": \"@rax-materials/scaffolds-app-js\"\n}\n"
  },
  {
    "path": "examples/event-handler/src/app.js",
    "content": "import { runApp } from 'rax-app';\nimport appConfig from './app.json';\n\nrunApp(appConfig);\n"
  },
  {
    "path": "examples/event-handler/src/app.json",
    "content": "{\n  \"routes\": [\n    {\n      \"path\": \"/\",\n      \"source\": \"pages/Home/index\"\n    }\n  ],\n  \"window\": {\n    \"title\": \"Rax App\"\n  }\n}\n"
  },
  {
    "path": "examples/event-handler/src/components/CustomComp/index.css",
    "content": ".logo {\n  width: 200rpx;\n  height: 180rpx;\n  margin-bottom: 20rpx;\n}"
  },
  {
    "path": "examples/event-handler/src/components/CustomComp/index.jsx",
    "content": "import { createElement } from 'rax';\nimport Image from 'rax-image';\n\nimport './index.css';\n\nexport default (props) => {\n  const { uri } = props;\n  const source = { uri };\n  return (\n    <Image\n      className=\"logo\"\n      source={source}\n    />\n  );\n};\n"
  },
  {
    "path": "examples/event-handler/src/document/index.jsx",
    "content": "import { createElement } from 'rax';\nimport { Root, Style, Script} from 'rax-document';\n\nfunction Document() {\n  return (\n    <html>\n      <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover\" />\n        <title>rax-materials-basic-app</title>\n        <Style />\n      </head>\n      <body>\n        {/* root container */}\n        <Root />\n        <Script />\n      </body>\n    </html>\n  );\n}\nexport default Document;\n"
  },
  {
    "path": "examples/event-handler/src/pages/Home/index.css",
    "content": ".home {\n  align-items: center;\n  margin-top: 200rpx;\n}\n\n.title {\n  font-size: 45rpx;\n  font-weight: bold;\n  margin: 20rpx 0;\n}\n\n.info {\n  font-size: 36rpx;\n  margin: 8rpx 0;\n  color: #555;\n}\n"
  },
  {
    "path": "examples/event-handler/src/pages/Home/index.jsx",
    "content": "import { createElement } from 'rax';\nimport View from 'rax-view';\nimport Text from 'rax-text';\nimport Image from 'rax-image';\n\nimport './index.css';\n\nimport CustomComp from '../../components/CustomComp';\n\nexport default function Home() {\n  function noop() {}\n  return (\n    <View className=\"home\">\n      <View className=\"test\" onClick={noop}>onClick -> onTap (alibaba miniapp) && bindtap (wechat miniprogram) in rax-view</View>\n      <Text className=\"test\" onClick={noop}>onClick -> bindtap (wechat miniprogram) in rax-text</Text>\n      <Image onClick={noop} onChange={noop}>onClick/onChange are not transformed (alibaba miniapp) && onClick -> bindonClick/onChange -> bindonChange (wechat miniprogram)</Image>\n      <button className=\"test\" style={{color: 'red'}} onClick={noop} onChange={noop}>onClick -> onTap (alibaba miniapp) && onClick -> bindtap (wechat miniprogram) && onChange -> bindchange (wechat miniprogram) </button>\n      <CustomComp onClick={noop} onChange={noop}>not transformed</CustomComp>\n    </View>\n  );\n}\n"
  },
  {
    "path": "examples/get-element/.eslintrc.js",
    "content": "module.exports = {\n  extends: ['rax']\n};"
  },
  {
    "path": "examples/get-element/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n*~\n*.swp\n*.log\n\n.DS_Store\n.idea/\n.temp/\n\nbuild/\ndist/\nlib/\ncoverage/\nnode_modules/\n\ntemplate.yml\n"
  },
  {
    "path": "examples/get-element/README.md",
    "content": "# rax-materials-basic-app\n\n## Getting Started\n\n### `npm run start`\n\nRuns the app in development mode.\n\nOpen [http://localhost:9999](http://localhost:9999) to view it in the browser.\n\nThe page will reload if you make edits.\n\n### `npm run build`\n\nBuilds the app for production to the `build` folder.\n"
  },
  {
    "path": "examples/get-element/abc.json",
    "content": "{\n  \"type\": \"rax\",\n  \"builder\": \"@ali/builder-rax-v1\",\n  \"info\": {\n    \"raxVersion\": \"1.x\"\n  }\n}\n"
  },
  {
    "path": "examples/get-element/build.json",
    "content": "{\n  \"inlineStyle\": false,\n  \"plugins\": [\n    [\n      \"build-plugin-rax-app\",\n      {\n        \"targets\": [\n          \"miniapp\",\n          \"wechat-miniprogram\"\n        ],\n        \"miniapp\": {\n          \"buildType\": \"runtime\"\n        },\n        \"wechat-miniprogram\": {\n          \"buildType\": \"runtime\"\n        }\n      }\n    ]\n  ]\n}\n"
  },
  {
    "path": "examples/get-element/package.json",
    "content": "{\n  \"name\": \"@rax-materials/scaffolds-app-js\",\n  \"author\": \"rax\",\n  \"description\": \"Rax 无线跨端应用工程，使用 JavaScript。\",\n  \"version\": \"0.1.0\",\n  \"scripts\": {\n    \"build\": \"build-scripts build\",\n    \"start\": \"build-scripts start\",\n    \"lint\": \"eslint --ext .js --ext .jsx ./\"\n  },\n  \"dependencies\": {\n    \"rax\": \"^1.1.0\",\n    \"rax-app\": \"^2.0.0\",\n    \"driver-universal\": \"^3.0.0\",\n    \"rax-image\": \"^2.0.0\",\n    \"rax-link\": \"^1.0.1\",\n    \"rax-text\": \"^1.0.0\",\n    \"rax-view\": \"^1.0.0\",\n    \"rax-document\": \"^0.1.0\"\n  },\n  \"devDependencies\": {\n    \"@alib/build-scripts\": \"^0.1.0\",\n    \"babel-eslint\": \"^10.0.3\",\n    \"build-plugin-rax-app\": \"^5.0.0\",\n    \"eslint\": \"^6.8.0\",\n    \"eslint-config-rax\": \"^0.1.0\",\n    \"eslint-plugin-import\": \"^2.20.0\",\n    \"eslint-plugin-module\": \"^0.1.0\",\n    \"eslint-plugin-react\": \"^7.18.0\"\n  },\n  \"private\": true,\n  \"originTemplate\": \"@rax-materials/scaffolds-app-js\"\n}\n"
  },
  {
    "path": "examples/get-element/src/app.js",
    "content": "import { runApp, useAppLaunch, useAppShow, useAppHide, useAppShare, useAppError } from 'rax-app';\nimport appConfig from './app.json';\n\nuseAppLaunch((options) => {\n  console.log('app launch', options);\n});\n\nuseAppShow((options) => {\n  console.log('app show', options);\n});\n\nuseAppHide(() => {\n  console.log('app hide');\n});\n\nuseAppShare(() => {\n  return {\n    title: '分享标题',\n    desc: '分享详细说明',\n    path: 'pages/Home/index'\n  };\n});\n\nuseAppError(() => {\n  console.log('app error');\n});\n\nrunApp(appConfig);\n"
  },
  {
    "path": "examples/get-element/src/app.json",
    "content": "{\n  \"routes\": [\n    {\n      \"path\": \"/\",\n      \"source\": \"pages/Home/index\"\n    }\n  ],\n  \"window\": {\n    \"title\": \"Rax App\"\n  }\n}\n"
  },
  {
    "path": "examples/get-element/src/components/Logo/index.css",
    "content": ".logo {\n  width: 200rpx;\n  height: 180rpx;\n  margin-bottom: 20rpx;\n}"
  },
  {
    "path": "examples/get-element/src/components/Logo/index.jsx",
    "content": "import { createElement } from 'rax';\nimport Image from 'rax-image';\n\nimport './index.css';\n\nexport default (props) => {\n  const { uri } = props;\n  const source = { uri };\n  return (\n    <Image\n      className=\"logo\"\n      source={source}\n    />\n  );\n};\n"
  },
  {
    "path": "examples/get-element/src/document/index.jsx",
    "content": "import { createElement } from 'rax';\nimport { Root, Style, Script} from 'rax-document';\n\nfunction Document() {\n  return (\n    <html>\n      <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover\" />\n        <title>rax-materials-basic-app</title>\n        <Style />\n      </head>\n      <body>\n        {/* root container */}\n        <Root />\n        <Script />\n      </body>\n    </html>\n  );\n}\nexport default Document;\n"
  },
  {
    "path": "examples/get-element/src/pages/Home/index.css",
    "content": ".home {\n  align-items: center;\n  margin-top: 200rpx;\n}\n\n.title {\n  font-size: 45rpx;\n  font-weight: bold;\n  margin: 20rpx 0;\n}\n\n.info {\n  font-size: 36rpx;\n  margin: 8rpx 0;\n  color: #555;\n}\n"
  },
  {
    "path": "examples/get-element/src/pages/Home/index.jsx",
    "content": "import { createElement, useEffect } from 'rax';\nimport View from 'rax-view';\nimport Text from 'rax-text';\n\nimport './index.css';\n\nimport Logo from '../../components/Logo';\n\nexport default function Home() {\n  useEffect(() => {\n    const father1 = document.getElementById('father');\n    const father2 = document.querySelector('#father');\n    const father3 = document.querySelectorAll('#father');\n\n    console.log('Home -> father1', father1);\n    console.log('Home -> father2', father2);\n    console.log('Home -> father3', father3);\n\n    const home1 = document.getElementsByClassName('home');\n    const home2 = document.querySelector('.home');\n    const home3 = document.querySelectorAll('.home');\n    console.log('Home -> home1', home1);\n    console.log('Home -> home2', home2);\n    console.log('Home -> home3', home3);\n\n    const div1 = document.getElementsByTagName('div');\n    const div2 = document.querySelector('div');\n    const div3 = document.querySelectorAll('div');\n    console.log('Home -> div1', div1);\n    console.log('Home -> div2', div2);\n    console.log('Home -> div3', div3);\n\n    const child = document.getElementById('child1');\n    const subDiv1 = child.getElementsByTagName('div');\n    const subDiv2 = child.querySelector('div');\n    const subDiv3 = child.querySelectorAll('div');\n    console.log('Home -> subDiv1', subDiv1);\n    console.log('Home -> subDiv2', subDiv2);\n    console.log('Home -> subDiv3', subDiv3);\n\n    const red1 = child.getElementsByClassName('red');\n    const red2 = child.querySelector('.red');\n    const red3 = child.querySelectorAll('.red');\n    console.log('Home -> red1', red1);\n    console.log('Home -> red2', red2);\n    console.log('Home -> red3', red3);\n  });\n  return (\n    <View id=\"father\" className=\"home\">\n      <div id=\"child1\" className=\"son\">\n        <div className=\"red\"></div>\n        <div className=\"green\"></div>\n        <div className=\"red\"></div>\n      </div>\n      <div id=\"child2\" className=\"son\"></div>\n      <div id=\"child3\" className=\"son\"></div>\n      <div id=\"child4\" className=\"son\"></div>\n      <div id=\"child5\" className=\"son\"></div>\n    </View>\n  );\n}\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/.eslintrc.js",
    "content": "module.exports = {\n  extends: ['rax']\n};"
  },
  {
    "path": "examples/page-lifecycle-with-router/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n*~\n*.swp\n*.log\n\n.DS_Store\n.idea/\n.temp/\n\nbuild/\ndist/\nlib/\ncoverage/\nnode_modules/\n\ntemplate.yml\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/README.md",
    "content": "# rax-materials-basic-app\n\n## Getting Started\n\n### `npm run start`\n\nRuns the app in development mode.\n\nOpen [http://localhost:9999](http://localhost:9999) to view it in the browser.\n\nThe page will reload if you make edits.\n\n### `npm run build`\n\nBuilds the app for production to the `build` folder.\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/build.json",
    "content": "{\n  \"inlineStyle\": false,\n  \"plugins\": [\n    [\n      \"build-plugin-rax-app\",\n      {\n        \"targets\": [\n          \"miniapp\",\n          \"wechat-miniprogram\"\n        ],\n        \"miniapp\": {\n          \"buildType\": \"runtime\"\n        },\n        \"wechat-miniprogram\": {\n          \"buildType\": \"runtime\"\n        }\n      }\n    ]\n  ]\n}\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/package.json",
    "content": "{\n  \"name\": \"@rax-materials/scaffolds-app-js\",\n  \"author\": \"rax\",\n  \"description\": \"Rax 无线跨端应用工程，使用 JavaScript。\",\n  \"version\": \"0.1.0\",\n  \"scripts\": {\n    \"build\": \"build-scripts build\",\n    \"start\": \"build-scripts start\",\n    \"lint\": \"eslint --ext .js --ext .jsx ./\"\n  },\n  \"dependencies\": {\n    \"rax\": \"^1.1.0\",\n    \"rax-app\": \"^2.0.0\",\n    \"driver-universal\": \"^3.0.0\",\n    \"rax-image\": \"^2.0.0\",\n    \"rax-link\": \"^1.0.1\",\n    \"rax-text\": \"^1.0.0\",\n    \"rax-view\": \"^1.0.0\",\n    \"rax-document\": \"^0.1.0\"\n  },\n  \"devDependencies\": {\n    \"@alib/build-scripts\": \"^0.1.0\",\n    \"babel-eslint\": \"^10.0.3\",\n    \"build-plugin-rax-app\": \"^5.0.0\",\n    \"eslint\": \"^6.8.0\",\n    \"eslint-config-rax\": \"^0.1.0\",\n    \"eslint-plugin-import\": \"^2.20.0\",\n    \"eslint-plugin-module\": \"^0.1.0\",\n    \"eslint-plugin-react\": \"^7.18.0\"\n  },\n  \"private\": true,\n  \"originTemplate\": \"@rax-materials/scaffolds-app-js\"\n}\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/src/app.js",
    "content": "import { runApp } from 'rax-app';\nimport appConfig from './app.json';\n\nrunApp(appConfig);\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/src/app.json",
    "content": "{\n  \"routes\": [\n    {\n      \"path\": \"/\",\n      \"source\": \"pages/Home/index\"\n    },\n    {\n      \"path\": \"/about\",\n      \"source\": \"pages/About/index\"\n    }\n  ],\n  \"window\": {\n    \"title\": \"Rax App\",\n    \"pullRefresh\": true\n  },\n  \"tabBar\": {\n    \"textColor\": \"#999\",\n    \"selectedColor\": \"#666\",\n    \"backgroundColor\": \"#f8f8f8\",\n    \"items\": [\n      {\n        \"name\": \"home\",\n        \"path\": \"/\",\n        \"icon\": \"https://gw.alicdn.com/tfs/TB1ypSMTcfpK1RjSZFOXXa6nFXa-144-144.png\",\n        \"activeIcon\": \"https://gw.alicdn.com/tfs/TB1NBiCTgHqK1RjSZFPXXcwapXa-144-144.png\"\n      },\n      {\n        \"name\": \"about\",\n        \"path\": \"/about\",\n        \"icon\": \"https://gw.alicdn.com/tfs/TB1ypSMTcfpK1RjSZFOXXa6nFXa-144-144.png\",\n        \"activeIcon\": \"https://gw.alicdn.com/tfs/TB1NBiCTgHqK1RjSZFPXXcwapXa-144-144.png\"\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/src/components/Logo/index.css",
    "content": ".logo {\n  width: 200rpx;\n  height: 180rpx;\n  margin-bottom: 20rpx;\n}"
  },
  {
    "path": "examples/page-lifecycle-with-router/src/components/Logo/index.jsx",
    "content": "import { createElement } from 'rax';\nimport Image from 'rax-image';\n\nimport './index.css';\n\nexport default (props) => {\n  const { uri } = props;\n  const source = { uri };\n  return (\n    <Image\n      className=\"logo\"\n      source={source}\n    />\n  );\n};\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/src/document/index.jsx",
    "content": "import { createElement } from 'rax';\nimport { Root, Style, Script} from 'rax-document';\n\nfunction Document() {\n  return (\n    <html>\n      <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover\" />\n        <title>rax-materials-basic-app</title>\n        <Style />\n      </head>\n      <body>\n        {/* root container */}\n        <Root />\n        <Script />\n      </body>\n    </html>\n  );\n}\nexport default Document;\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/src/pages/About/index.css",
    "content": ".home {\n  align-items: center;\n  margin-top: 200rpx;\n}\n\n.title {\n  font-size: 45rpx;\n  font-weight: bold;\n  margin: 20rpx 0;\n}\n\n.info {\n  font-size: 36rpx;\n  margin: 8rpx 0;\n  color: #555;\n}\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/src/pages/About/index.jsx",
    "content": "import { createElement } from 'rax';\nimport { registerNativeEventListeners, addNativeEventListener, removeNativeEventListener, usePageShow, usePageHide } from 'rax-app';\nimport View from 'rax-view';\nimport Text from 'rax-text';\n\nimport './index.css';\n\nimport Logo from '../../components/Logo';\n\nfunction handler(lifeCycle) {\n  return () => {\n    console.log('about page ' + lifeCycle);\n    if (lifeCycle === 'onShareAppMessage') {\n      return {\n        title: '分享标题',\n        desc: '分享详细说明',\n        path: 'pages/Home/index'\n      };\n    }\n  };\n}\n\nconst lifeCycles = ['onLoad', 'onReady', 'onShow', 'onHide', 'onUnload', 'onShareAppMessage', 'onTitleClick', 'onOptionMenuClick', 'onPopMenuClick', 'onPullDownRefresh', 'onPullIntercept', 'onTabItemTap', 'onPageScroll', 'onReachBottom'];\n\nlifeCycles.forEach(lc => addNativeEventListener(lc, handler(lc)));\n\nfunction About(props) {\n  // To start listening for location changes...\n  let unlisten = props.history.listen(( action, location ) => {\n    console.log('in about page action', action);\n    console.log('in about page location', location);\n  });\n\n  usePageShow(() => {\n    console.log('about page show -- from usePageShow');\n  });\n  usePageHide(() => {\n    console.log('about page hide -- from usePageHide');\n  });\n\n  return (\n    <View className=\"home\">\n      <Logo uri=\"//gw.alicdn.com/tfs/TB1MRC_cvb2gK0jSZK9XXaEgFXa-1701-1535.png\" />\n      <Text className=\"title\">这里是 About 页面</Text>\n      <Text className=\"info\" onClick={() => {\n        props.history.push('/about');\n      }}>history.push Home 页面</Text>\n      <Text className=\"info\" onClick={() => {\n        props.history.replace('/about');\n      }}>history.replace Home 页面</Text>\n      <Text className=\"info\" onClick={() => {\n        props.history.goBack();\n      }}>history.back Home 页面</Text>\n\n    </View>\n  );\n}\n\nregisterNativeEventListeners(About, ['onLoad', 'onReady', 'onShow', 'onHide', 'onUnload', 'onShareAppMessage', 'onTitleClick', 'onOptionMenuClick', 'onPopMenuClick', 'onPullDownRefresh', 'onPullIntercept', 'onTabItemTap', 'onPageScroll', 'onReachBottom']);\n\nexport default About;\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/src/pages/Home/index.css",
    "content": ".home {\n  align-items: center;\n  margin-top: 200rpx;\n}\n\n.title {\n  font-size: 45rpx;\n  font-weight: bold;\n  margin: 20rpx 0;\n}\n\n.info {\n  font-size: 36rpx;\n  margin: 8rpx 0;\n  color: #555;\n}\n"
  },
  {
    "path": "examples/page-lifecycle-with-router/src/pages/Home/index.jsx",
    "content": "import { createElement } from 'rax';\nimport { registerNativeEventListeners, addNativeEventListener, removeNativeEventListener, usePageShow, usePageHide } from 'rax-app';\nimport View from 'rax-view';\nimport Text from 'rax-text';\n\nimport './index.css';\n\nimport Logo from '../../components/Logo';\n\nfunction handler(lifeCycle) {\n  return () => {\n    console.log('home page ' + lifeCycle);\n    if (lifeCycle === 'onShareAppMessage') {\n      return {\n        title: '分享标题',\n        desc: '分享详细说明',\n        path: 'pages/Home/index'\n      };\n    }\n  };\n}\n\nconst lifeCycles = ['onLoad', 'onReady', 'onShow', 'onHide', 'onUnload', 'onShareAppMessage', 'onTitleClick', 'onOptionMenuClick', 'onPopMenuClick', 'onPullDownRefresh', 'onPullIntercept', 'onTabItemTap', 'onPageScroll', 'onReachBottom'];\n\nlifeCycles.forEach(lc => addNativeEventListener(lc, handler(lc)));\n\nfunction Home(props) {\n  // To start listening for location changes...\n  let unlisten = props.history.listen(( action, location ) => {\n    console.log('in home page action', action);\n    console.log('in home page location', location);\n  });\n\n  usePageShow(() => {\n    console.log('home page show -- from usePageShow');\n  });\n  usePageHide(() => {\n    console.log('home page hide -- from usePageHide');\n  });\n  return (\n    <View className=\"home\">\n      <Logo uri=\"//gw.alicdn.com/tfs/TB1MRC_cvb2gK0jSZK9XXaEgFXa-1701-1535.png\" />\n      <Text className=\"title\">这里是 Home 页面</Text>\n      <Text className=\"info\" onClick={() => {\n        props.history.push('/about');\n      }}>history.push About 页面</Text>\n      <Text className=\"info\" onClick={() => {\n        props.history.replace('/about');\n      }}>history.replace About 页面</Text>\n    </View>\n  );\n}\n\nregisterNativeEventListeners(Home, ['onLoad', 'onReady', 'onShow', 'onHide', 'onUnload', 'onShareAppMessage', 'onTitleClick', 'onOptionMenuClick', 'onPopMenuClick', 'onPullDownRefresh', 'onPullIntercept', 'onTabItemTap', 'onPageScroll', 'onReachBottom']);\n\nexport default Home;\n"
  },
  {
    "path": "examples/use-rax-compiled-component-in-runtime-miniapp/.eslintrc.js",
    "content": "module.exports = {\n  extends: ['rax']\n};"
  },
  {
    "path": "examples/use-rax-compiled-component-in-runtime-miniapp/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n*~\n*.swp\n*.log\n\n.DS_Store\n.idea/\n.temp/\n\nbuild/\ndist/\nlib/\ncoverage/\nnode_modules/\n\ntemplate.yml\n"
  },
  {
    "path": "examples/use-rax-compiled-component-in-runtime-miniapp/README.md",
    "content": "# rax-materials-basic-app\n\n## Getting Started\n\n### `npm run start`\n\nRuns the app in development mode.\n\nOpen [http://localhost:9999](http://localhost:9999) to view it in the browser.\n\nThe page will reload if you make edits.\n\n### `npm run build`\n\nBuilds the app for production to the `build` folder.\n"
  },
  {
    "path": "examples/use-rax-compiled-component-in-runtime-miniapp/abc.json",
    "content": "{\n  \"type\": \"rax\",\n  \"builder\": \"@ali/builder-rax-v1\",\n  \"info\": {\n    \"raxVersion\": \"1.x\"\n  }\n}\n"
  },
  {
    "path": "examples/use-rax-compiled-component-in-runtime-miniapp/build.json",
    "content": "{\n  \"inlineStyle\": false,\n  \"plugins\": [\n    [\n      \"build-plugin-rax-app\",\n      {\n        \"targets\": [\n          \"miniapp\"\n        ],\n        \"miniapp\": {\n          \"buildType\": \"runtime\"\n        },\n        \"wechat-miniprogram\": {\n          \"buildType\": \"runtime\"\n        }\n      }\n    ]\n  ]\n}\n"
  },
  {
    "path": "examples/use-rax-compiled-component-in-runtime-miniapp/package.json",
    "content": "{\n  \"name\": \"@rax-materials/scaffolds-app-js\",\n  \"author\": \"rax\",\n  \"description\": \"Rax 无线跨端应用工程，使用 JavaScript。\",\n  \"version\": \"0.1.0\",\n  \"scripts\": {\n    \"build\": \"build-scripts build\",\n    \"start\": \"build-scripts start\",\n    \"lint\": \"eslint --ext .js --ext .jsx ./\"\n  },\n  \"dependencies\": {\n    \"driver-universal\": \"^3.0.0\",\n    \"rax\": \"^1.1.0\",\n    \"rax-app\": \"^2.0.0\",\n    \"rax-document\": \"^0.1.0\",\n    \"rax-image\": \"^2.0.0\",\n    \"rax-link\": \"^1.0.1\",\n    \"rax-modal\": \"^1.5.4\",\n    \"rax-text\": \"^1.0.0\",\n    \"rax-view\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"@alib/build-scripts\": \"^0.1.0\",\n    \"babel-eslint\": \"^10.0.3\",\n    \"build-plugin-rax-app\": \"^5.0.0\",\n    \"eslint\": \"^6.8.0\",\n    \"eslint-config-rax\": \"^0.1.0\",\n    \"eslint-plugin-import\": \"^2.20.0\",\n    \"eslint-plugin-module\": \"^0.1.0\",\n    \"eslint-plugin-react\": \"^7.18.0\"\n  },\n  \"private\": true,\n  \"originTemplate\": \"@rax-materials/scaffolds-app-js\"\n}\n"
  },
  {
    "path": "examples/use-rax-compiled-component-in-runtime-miniapp/src/app.js",
    "content": "import { runApp } from 'rax-app';\nimport appConfig from './app.json';\n\nrunApp(appConfig);\n"
  },
  {
    "path": "examples/use-rax-compiled-component-in-runtime-miniapp/src/app.json",
    "content": "{\n  \"routes\": [\n    {\n      \"path\": \"/\",\n      \"source\": \"pages/Home/index\"\n    }\n  ],\n  \"window\": {\n    \"title\": \"Rax App\"\n  }\n}\n"
  },
  {
    "path": "examples/use-rax-compiled-component-in-runtime-miniapp/src/document/index.jsx",
    "content": "import { createElement } from 'rax';\nimport { Root, Style, Script} from 'rax-document';\n\nfunction Document() {\n  return (\n    <html>\n      <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover\" />\n        <title>rax-materials-basic-app</title>\n        <Style />\n      </head>\n      <body>\n        {/* root container */}\n        <Root />\n        <Script />\n      </body>\n    </html>\n  );\n}\nexport default Document;\n"
  },
  {
    "path": "examples/use-rax-compiled-component-in-runtime-miniapp/src/pages/Home/index.css",
    "content": ".home {\n  align-items: center;\n  margin-top: 200rpx;\n}\n\n.title {\n  font-size: 45rpx;\n  font-weight: bold;\n  margin: 20rpx 0;\n}\n\n.info {\n  font-size: 36rpx;\n  margin: 8rpx 0;\n  color: #555;\n}\n"
  },
  {
    "path": "examples/use-rax-compiled-component-in-runtime-miniapp/src/pages/Home/index.jsx",
    "content": "import { createElement, useState } from 'rax';\nimport View from 'rax-view';\nimport Text from 'rax-text';\nimport Modal from 'rax-modal';\n\nimport './index.css';\n\nconst Home = () => {\n  const [visible, setVisible] = useState(false);\n  return (\n    <View>\n      <View onClick={() => {\n        setVisible(true);\n      }}>open</View>\n      <Modal\n        visible={visible}\n        onHide={() => {\n          setVisible(false);\n        }}\n      >\n        <Text>Hello, world</Text>\n      </Modal>\n    </View>\n  );\n};\n\nexport default Home;\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/.eslintrc.js",
    "content": "module.exports = {\n  extends: ['rax']\n};"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n*~\n*.swp\n*.log\n\n.DS_Store\n.idea/\n.temp/\n\nbuild/\ndist/\nlib/\ncoverage/\nnode_modules/\n\ntemplate.yml\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/README.md",
    "content": "# rax-materials-basic-app\n\n## Getting Started\n\n### `npm run start`\n\nRuns the app in development mode.\n\nOpen [http://localhost:9999](http://localhost:9999) to view it in the browser.\n\nThe page will reload if you make edits.\n\n### `npm run build`\n\nBuilds the app for production to the `build` folder.\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/build.json",
    "content": "{\n  \"inlineStyle\": false,\n  \"plugins\": [\n    [\n      \"build-plugin-rax-app\",\n      {\n        \"targets\": [\n          \"miniapp\",\n          \"wechat-miniprogram\"\n        ],\n        \"miniapp\": {\n          \"buildType\": \"runtime\"\n        },\n        \"wechat-miniprogram\": {\n          \"buildType\": \"runtime\"\n        }\n      }\n    ]\n  ]\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/package.json",
    "content": "{\n  \"name\": \"@rax-materials/scaffolds-app-js\",\n  \"author\": \"rax\",\n  \"description\": \"Rax 无线跨端应用工程，使用 JavaScript。\",\n  \"version\": \"0.1.0\",\n  \"scripts\": {\n    \"build\": \"build-scripts build\",\n    \"start\": \"build-scripts start\",\n    \"lint\": \"eslint --ext .js --ext .jsx ./\"\n  },\n  \"dependencies\": {\n    \"driver-universal\": \"^3.0.0\",\n    \"mini-ali-ui\": \"^1.1.4\",\n    \"rax\": \"^1.1.0\",\n    \"rax-app\": \"^2.0.0\",\n    \"rax-document\": \"^0.1.0\",\n    \"rax-image\": \"^2.0.0\",\n    \"rax-link\": \"^1.0.1\",\n    \"rax-text\": \"^1.0.0\",\n    \"rax-view\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"@alib/build-scripts\": \"^0.1.0\",\n    \"babel-eslint\": \"^10.0.3\",\n    \"build-plugin-rax-app\": \"^5.0.0\",\n    \"eslint\": \"^6.8.0\",\n    \"eslint-config-rax\": \"^0.1.0\",\n    \"eslint-plugin-import\": \"^2.20.0\",\n    \"eslint-plugin-module\": \"^0.1.0\",\n    \"eslint-plugin-react\": \"^7.18.0\"\n  },\n  \"private\": true,\n  \"originTemplate\": \"@rax-materials/scaffolds-app-js\"\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/app.js",
    "content": "import { runApp } from 'rax-app';\nimport appConfig from './app.json';\n\nrunApp(appConfig);\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/app.json",
    "content": "{\n  \"routes\": [\n    {\n      \"path\": \"/\",\n      \"source\": \"pages/Home/index\"\n    }\n  ],\n  \"window\": {\n    \"title\": \"Rax App\"\n  }\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/components/Test/index.ali.jsx",
    "content": "import { createElement } from 'rax';\nimport View from 'rax-view';\n\nimport Test from '../../public/AliNativeComp/index';\nimport Title from 'mini-ali-ui/es/title/index';\n\nexport default function Home() {\n  return (\n    <View className=\"home\">\n      <Title\n        hasLine={true}\n        type=\"arrow\"\n        onActionTap={() => {\n          console.log('标题被击中了');\n        }}\n      >我是 mini-ali-ui 的 title 组件</Title>\n      <Test onClick={() => {\n        console.log('我被击中了');\n      }}>\n        <View slot=\"header\">我是 header</View>\n        <View slot=\"footer\">我是 footer</View>\n      </Test>\n    </View>\n  );\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/components/Test/index.wechat.jsx",
    "content": "import { createElement } from 'rax';\nimport View from 'rax-view';\n\nimport Test from '../../public/WechatNativeComp/index';\n\nexport default function Home() {\n  return (\n    <View className=\"home\">\n      <Test onClick={() => {\n        console.log('我被击中了');\n      }}>\n        <View slot=\"header\">我是 header</View>\n        <View slot=\"footer\">我是 footer</View>\n      </Test>\n    </View>\n  );\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/document/index.jsx",
    "content": "import { createElement } from 'rax';\nimport { Root, Style, Script} from 'rax-document';\n\nfunction Document() {\n  return (\n    <html>\n      <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover\" />\n        <title>rax-materials-basic-app</title>\n        <Style />\n      </head>\n      <body>\n        {/* root container */}\n        <Root />\n        <Script />\n      </body>\n    </html>\n  );\n}\nexport default Document;\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/pages/Home/index.css",
    "content": ".home {\n  align-items: center;\n  margin-top: 200rpx;\n}\n\n.title {\n  font-size: 45rpx;\n  font-weight: bold;\n  margin: 20rpx 0;\n}\n\n.info {\n  font-size: 36rpx;\n  margin: 8rpx 0;\n  color: #555;\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/pages/Home/index.jsx",
    "content": "import { createElement } from 'rax';\nimport View from 'rax-view';\n\nimport './index.css';\nimport Test from '../../components/Test';\n\nexport default function Home() {\n  return (\n    <View className=\"home\">\n      <Test />\n    </View>\n  );\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/public/AliNativeComp/index.acss",
    "content": ".test {\n  color: #F3BF37;\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/public/AliNativeComp/index.axml",
    "content": "<view class=\"test\" onTap=\"onClick\">\n  <slot name=\"header\" />\n  <view>我是小程序原生自定义组件</view>\n  <slot name=\"footer\" />\n</view>\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/public/AliNativeComp/index.js",
    "content": "Component({\n  methods: {\n    onClick() {\n      this.props.onClick && this.props.onClick();\n    }\n  }\n});\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/public/AliNativeComp/index.json",
    "content": "{\n  \"component\": true\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/public/WechatNativeComp/index.js",
    "content": "Component({\n  options: {\n    multipleSlots: true\n  },\n  methods: {\n    onClick() {\n      this.triggerEvent('click');\n    }\n  }\n});\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/public/WechatNativeComp/index.json",
    "content": "{\n  \"component\": true\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/public/WechatNativeComp/index.wxml",
    "content": "<view class=\"test\" bindtap=\"onClick\">\n  <slot name=\"header\" />\n  <view>我是小程序原生自定义组件</view>\n  <slot name=\"footer\" />\n</view>\n"
  },
  {
    "path": "examples/with-miniapp-native-custom-component/src/public/WechatNativeComp/index.wxss",
    "content": ".test {\n  color: #F3BF37;\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-page/.eslintrc.js",
    "content": "module.exports = {\n  extends: ['rax']\n};"
  },
  {
    "path": "examples/with-miniapp-native-page/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n*~\n*.swp\n*.log\n\n.DS_Store\n.idea/\n.temp/\n\nbuild/\ndist/\nlib/\ncoverage/\nnode_modules/\n\ntemplate.yml\n"
  },
  {
    "path": "examples/with-miniapp-native-page/README.md",
    "content": "# rax-materials-basic-app\n\n## Getting Started\n\n### `npm run start`\n\nRuns the app in development mode.\n\nOpen [http://localhost:9999](http://localhost:9999) to view it in the browser.\n\nThe page will reload if you make edits.\n\n### `npm run build`\n\nBuilds the app for production to the `build` folder.\n"
  },
  {
    "path": "examples/with-miniapp-native-page/build.json",
    "content": "{\n  \"inlineStyle\": false,\n  \"plugins\": [\n    [\n      \"build-plugin-rax-app\",\n      {\n        \"targets\": [\n          \"miniapp\"\n        ],\n        \"miniapp\": {\n          \"buildType\": \"runtime\"\n        },\n        \"wechat-miniprogram\": {\n          \"buildType\": \"runtime\"\n        }\n      }\n    ]\n  ]\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-page/package.json",
    "content": "{\n  \"name\": \"@rax-materials/scaffolds-app-js\",\n  \"author\": \"rax\",\n  \"description\": \"Rax 无线跨端应用工程，使用 JavaScript。\",\n  \"version\": \"0.1.0\",\n  \"scripts\": {\n    \"build\": \"build-scripts build\",\n    \"start\": \"build-scripts start\",\n    \"lint\": \"eslint --ext .js --ext .jsx ./\"\n  },\n  \"dependencies\": {\n    \"rax\": \"^1.1.0\",\n    \"rax-app\": \"^2.0.0\",\n    \"driver-universal\": \"^3.0.0\",\n    \"rax-image\": \"^2.0.0\",\n    \"rax-link\": \"^1.0.1\",\n    \"rax-text\": \"^1.0.0\",\n    \"rax-view\": \"^1.0.0\",\n    \"rax-document\": \"^0.1.0\"\n  },\n  \"devDependencies\": {\n    \"@alib/build-scripts\": \"^0.1.0\",\n    \"babel-eslint\": \"^10.0.3\",\n    \"build-plugin-rax-app\": \"^5.0.0\",\n    \"eslint\": \"^6.8.0\",\n    \"eslint-config-rax\": \"^0.1.0\",\n    \"eslint-plugin-import\": \"^2.20.0\",\n    \"eslint-plugin-module\": \"^0.1.0\",\n    \"eslint-plugin-react\": \"^7.18.0\"\n  },\n  \"private\": true,\n  \"originTemplate\": \"@rax-materials/scaffolds-app-js\"\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/app.js",
    "content": "import { runApp } from 'rax-app';\nimport appConfig from './app.json';\n\nrunApp(appConfig);\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/app.json",
    "content": "{\n  \"routes\": [\n    {\n      \"path\": \"/\",\n      \"source\": \"pages/Home/index\"\n    },\n    {\n      \"path\": \"/native\",\n      \"source\": \"pages/NativeHome/index\"\n    }\n  ],\n  \"window\": {\n    \"title\": \"Rax App\"\n  }\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/components/Logo/index.css",
    "content": ".logo {\n  width: 200rpx;\n  height: 180rpx;\n  margin-bottom: 20rpx;\n}"
  },
  {
    "path": "examples/with-miniapp-native-page/src/components/Logo/index.jsx",
    "content": "import { createElement } from 'rax';\nimport Image from 'rax-image';\n\nimport './index.css';\n\nexport default (props) => {\n  const { uri } = props;\n  const source = { uri };\n  return (\n    <Image\n      className=\"logo\"\n      source={source}\n    />\n  );\n};\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/document/index.jsx",
    "content": "import { createElement } from 'rax';\nimport { Root, Style, Script} from 'rax-document';\n\nfunction Document() {\n  return (\n    <html>\n      <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover\" />\n        <title>rax-materials-basic-app</title>\n        <Style />\n      </head>\n      <body>\n        {/* root container */}\n        <Root />\n        <Script />\n      </body>\n    </html>\n  );\n}\nexport default Document;\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/pages/Home/index.css",
    "content": ".home {\n  align-items: center;\n  margin-top: 200rpx;\n}\n\n.title {\n  font-size: 45rpx;\n  font-weight: bold;\n  margin: 20rpx 0;\n}\n\n.info {\n  font-size: 36rpx;\n  margin: 8rpx 0;\n  color: #555;\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/pages/Home/index.jsx",
    "content": "import { createElement } from 'rax';\nimport View from 'rax-view';\nimport Text from 'rax-text';\n\nimport './index.css';\n\nimport Logo from '../../components/Logo';\n\nexport default function Home() {\n  return (\n    <View className=\"home\">\n      <Logo uri=\"//gw.alicdn.com/tfs/TB1MRC_cvb2gK0jSZK9XXaEgFXa-1701-1535.png\" />\n      <Text className=\"title\">Welcome to Your Rax App</Text>\n      <Text className=\"info\">More information about Rax</Text>\n      <Text className=\"info\">Visit https://rax.js.org</Text>\n    </View>\n  );\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/pages/NativeHome/index.acss",
    "content": ""
  },
  {
    "path": "examples/with-miniapp-native-page/src/pages/NativeHome/index.axml",
    "content": "\n<view>\n  <view>这里是原生页面</view>\n  <comp1></comp1>\n  <comp2></comp2>\n</view>\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/pages/NativeHome/index.js",
    "content": "Page({});\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/pages/NativeHome/index.json",
    "content": "{\n  \"usingComponents\": {\n    \"comp1\": \"../../public/components/comp1/index\",\n    \"comp2\": \"../../public/components/comp2/index\"\n  }\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/public/components/comp1/index.axml",
    "content": "<view>我是 comp1</view>\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/public/components/comp1/index.js",
    "content": "Component({});\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/public/components/comp1/index.json",
    "content": "{\n  \"component\": true\n}\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/public/components/comp2/index.axml",
    "content": "<view>我是 comp2</view>\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/public/components/comp2/index.js",
    "content": "Component({});\n"
  },
  {
    "path": "examples/with-miniapp-native-page/src/public/components/comp2/index.json",
    "content": "{\n  \"component\": true\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/.eslintrc.js",
    "content": "module.exports = {\n  extends: ['rax']\n};"
  },
  {
    "path": "examples/with-miniapp-plugin-component/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n*~\n*.swp\n*.log\n\n.DS_Store\n.idea/\n.temp/\n\nbuild/\ndist/\nlib/\ncoverage/\nnode_modules/\n\ntemplate.yml\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/README.md",
    "content": "# rax-materials-basic-app\n\n## Getting Started\n\n### `npm run start`\n\nRuns the app in development mode.\n\nOpen [http://localhost:9999](http://localhost:9999) to view it in the browser.\n\nThe page will reload if you make edits.\n\n### `npm run build`\n\nBuilds the app for production to the `build` folder.\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/ali-miniapp-plugin/api/data.js",
    "content": "var data = 'init data';\n\nfunction getData() {\n  return data;\n}\n\nfunction setData(value) {\n  data = value;\n}\n\nmodule.exports = {\n  getData: getData,\n  setData: setData\n};\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/ali-miniapp-plugin/components/test/index.acss",
    "content": ""
  },
  {
    "path": "examples/with-miniapp-plugin-component/ali-miniapp-plugin/components/test/index.axml",
    "content": "<view onTap=\"onClick\">\n  <view>{{pluginName}}</view>\n</view>\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/ali-miniapp-plugin/components/test/index.js",
    "content": "Component({\n  props: {\n    pluginName: 'plugin'\n  },\n  methods: {\n    onClick() {\n      const { pluginName } = this.props;\n      this.props.onTest && this.props.onTest(pluginName);\n    }\n  }\n});\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/ali-miniapp-plugin/components/test/index.json",
    "content": "{\n  \"component\": true\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/ali-miniapp-plugin/index.js",
    "content": "var data = require('./api/data');\n\nmodule.exports = {\n  getData: data.getData,\n  setData: data.setData\n};\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/ali-miniapp-plugin/pages/index/index.acss",
    "content": ""
  },
  {
    "path": "examples/with-miniapp-plugin-component/ali-miniapp-plugin/pages/index/index.axml",
    "content": "<view>Hello from plugin page</view>"
  },
  {
    "path": "examples/with-miniapp-plugin-component/ali-miniapp-plugin/pages/index/index.js",
    "content": "Page({});\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/ali-miniapp-plugin/pages/index/index.json",
    "content": "{}"
  },
  {
    "path": "examples/with-miniapp-plugin-component/ali-miniapp-plugin/plugin.json",
    "content": "{\n  \"publicComponents\": {\n    \"test\": \"components/test/index\"\n  },\n  \"publicPages\": {\n    \"hello-page\": \"pages/index/index\"\n  },\n  \"pages\": [\n    \"pages/index/index\"\n  ],\n  \"main\": \"index\"\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/build.json",
    "content": "{\n  \"inlineStyle\": false,\n  \"plugins\": [\n    [\n      \"build-plugin-rax-app\",\n      {\n        \"targets\": [\n          \"miniapp\",\n          \"wechat-miniprogram\"\n        ],\n        \"miniapp\": {\n          \"buildType\": \"runtime\"\n        },\n        \"wechat-miniprogram\": {\n          \"buildType\": \"runtime\"\n        }\n      }\n    ]\n  ]\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/mini.project.json",
    "content": "{\n  \"miniprogramRoot\": \"build/miniapp\",\n  \"pluginRoot\": \"ali-miniapp-plugin\",\n  \"compileType\": \"plugin\",\n  \"component2\": false\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/package.json",
    "content": "{\n  \"name\": \"@rax-materials/scaffolds-app-js\",\n  \"author\": \"rax\",\n  \"description\": \"Rax 无线跨端应用工程，使用 JavaScript。\",\n  \"version\": \"0.1.0\",\n  \"scripts\": {\n    \"build\": \"build-scripts build\",\n    \"start\": \"build-scripts start\",\n    \"lint\": \"eslint --ext .js --ext .jsx ./\"\n  },\n  \"dependencies\": {\n    \"rax\": \"^1.1.0\",\n    \"rax-app\": \"^2.0.0\",\n    \"driver-universal\": \"^3.0.0\",\n    \"rax-image\": \"^2.0.0\",\n    \"rax-link\": \"^1.0.1\",\n    \"rax-text\": \"^1.0.0\",\n    \"rax-view\": \"^1.0.0\",\n    \"rax-document\": \"^0.1.0\",\n    \"universal-env\": \"^3.0.0\"\n  },\n  \"devDependencies\": {\n    \"@alib/build-scripts\": \"^0.1.0\",\n    \"babel-eslint\": \"^10.0.3\",\n    \"build-plugin-rax-app\": \"^5.0.0\",\n    \"eslint\": \"^6.8.0\",\n    \"eslint-config-rax\": \"^0.1.0\",\n    \"eslint-plugin-import\": \"^2.20.0\",\n    \"eslint-plugin-module\": \"^0.1.0\",\n    \"eslint-plugin-react\": \"^7.18.0\"\n  },\n  \"private\": true,\n  \"originTemplate\": \"@rax-materials/scaffolds-app-js\"\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/project.config.json",
    "content": "{\n\t\"miniprogramRoot\": \"build/wechat-miniprogram/\",\n\t\"pluginRoot\": \"wechat-miniprogram-plugin/\",\n\t\"compileType\": \"plugin\",\n\t\"setting\": {\n\t\t\"urlCheck\": true,\n\t\t\"es6\": true,\n\t\t\"enhance\": false,\n\t\t\"postcss\": true,\n\t\t\"preloadBackgroundData\": false,\n\t\t\"minified\": true,\n\t\t\"newFeature\": false,\n\t\t\"coverView\": true,\n\t\t\"nodeModules\": false,\n\t\t\"autoAudits\": false,\n\t\t\"showShadowRootInWxmlPanel\": true,\n\t\t\"scopeDataCheck\": false,\n\t\t\"uglifyFileName\": false,\n\t\t\"checkInvalidKey\": true,\n\t\t\"checkSiteMap\": true,\n\t\t\"uploadWithSourceMap\": true,\n\t\t\"compileHotReLoad\": false,\n\t\t\"babelSetting\": {\n\t\t\t\"ignore\": [],\n\t\t\t\"disablePlugins\": [],\n\t\t\t\"outputPath\": \"\"\n\t\t},\n\t\t\"useIsolateContext\": true,\n\t\t\"useCompilerModule\": true,\n\t\t\"userConfirmedUseCompilerModuleSwitch\": false\n\t},\n\t\"appid\": \"wxc0575284fd6f4091\",\n\t\"projectname\": \"with-miniapp-plugin-component\",\n\t\"simulatorType\": \"wechat\",\n\t\"simulatorPluginLibVersion\": {},\n\t\"condition\": {}\n}"
  },
  {
    "path": "examples/with-miniapp-plugin-component/src/app.js",
    "content": "import { runApp } from 'rax-app';\nimport appConfig from './app.json';\n\nrunApp(appConfig);\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/src/app.json",
    "content": "{\n  \"routes\": [\n    {\n      \"path\": \"/\",\n      \"source\": \"pages/Home/index\"\n    }\n  ],\n  \"plugins\": {\n    \"myPlugin\": {\n      \"version\": \"dev\",\n      \"provider\": \"{{currentPluginId}}\"\n    }\n  },\n  \"window\": {\n    \"title\": \"Rax App\"\n  }\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/src/components/Test/index.ali.jsx",
    "content": "import { createElement, useState } from 'rax';\nimport View from 'rax-view';\n// eslint-disable-next-line\nimport Test from 'plugin://myPlugin/test';\n\nexport default function Home() {\n  function test(pluginName) {\n    console.log(`${pluginName}被触发`);\n  }\n  return (\n    <View className=\"home\">\n      {\n        [1, 2, 3, 4, 5, 6].map(item => {\n          return (\n            <View key={item}>\n              <Test\n                onTest={test}\n                pluginName={`插件 No.${item}`}\n              />\n            </View>\n          );\n        })\n      }\n    </View>\n  );\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/src/components/Test/index.jsx",
    "content": "import { createElement } from 'rax';\nimport { isWeb, isMiniApp } from 'universal-env';\nimport View from 'rax-view';\nimport Text from 'rax-text';\n\n\nexport default function Home() {\n  return (\n    <View className=\"home\">\n      <Text className=\"title\">这是 web 组件</Text>\n    </View>\n  );\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/src/components/Test/index.wechat.jsx",
    "content": "import { createElement, useState } from 'rax';\nimport View from 'rax-view';\nimport Text from 'rax-text';\n// eslint-disable-next-line\nimport Plugin from 'plugin://myPlugin/hello-component';\n\nexport default function Home() {\n  function test(pluginName) {\n    console.log(`${pluginName}被触发`);\n  }\n  const list = [1, 2, 3];\n  return (\n    <View className=\"home\">\n      {\n        [1, 2, 3, 4, 5, 6].map(item => {\n          return (\n            <View key={item}>\n              <Plugin list={list} onTest={() => {\n                test(item);\n              }} />\n            </View>\n          );\n        })\n      }\n\n    </View>\n  );\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/src/document/index.jsx",
    "content": "import { createElement } from 'rax';\nimport { Root, Style, Script} from 'rax-document';\n\nfunction Document() {\n  return (\n    <html>\n      <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover\" />\n        <title>rax-materials-basic-app</title>\n        <Style />\n      </head>\n      <body>\n        {/* root container */}\n        <Root />\n        <Script />\n      </body>\n    </html>\n  );\n}\nexport default Document;\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/src/pages/Home/index.css",
    "content": ".home {\n  align-items: center;\n  margin-top: 200rpx;\n}\n\n.title {\n  font-size: 45rpx;\n  font-weight: bold;\n  margin: 20rpx 0;\n}\n\n.info {\n  font-size: 36rpx;\n  margin: 8rpx 0;\n  color: #555;\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/src/pages/Home/index.jsx",
    "content": "import { createElement } from 'rax';\nimport View from 'rax-view';\n\nimport './index.css';\n\nimport Test from '../../components/Test';\n\n\nexport default function Home() {\n  return (\n    <View className=\"home\">\n      <Test />\n    </View>\n  );\n}\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/wechat-miniprogram-plugin/api/data.js",
    "content": "var data = 'init data';\n\nfunction getData() {\n  return data;\n}\n\nfunction setData(value) {\n  data = value;\n}\n\nmodule.exports = {\n  getData: getData,\n  setData: setData\n};\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/wechat-miniprogram-plugin/components/hello-component.js",
    "content": "// plugin/components/hello-component.js\nComponent({\n  properties: {\n    list: {\n      type: Array,\n      value: [],\n      observer: function(newVal, oldVal, changedPath) {\n        this.setData({ list: newVal });\n      }\n    }\n  },\n\n  data: {\n    list: []\n  },\n\n  methods: {\n    onClick() {\n      this.triggerEvent('Test');\n    }\n  }\n});\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/wechat-miniprogram-plugin/components/hello-component.json",
    "content": "{\n  \"component\": true,\n  \"usingComponents\": {}\n}"
  },
  {
    "path": "examples/with-miniapp-plugin-component/wechat-miniprogram-plugin/components/hello-component.wxml",
    "content": "<!--plugin/components/hello-component.wxml-->\n<view class=\"container\" bindtap=\"onClick\">\n  <text class=\"item\" wx:key=\"item\" wx:for=\"{{ list }}\">{{ item }}</text>\n</view>\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/wechat-miniprogram-plugin/components/hello-component.wxss",
    "content": "/* plugin/components/hello-component.wxss */\r\n.container {\r\n  margin: 1em;\r\n}\r\n.item {\r\n  display: block;\r\n}"
  },
  {
    "path": "examples/with-miniapp-plugin-component/wechat-miniprogram-plugin/index.js",
    "content": "module.exports = {\n  sayHello: function() {\n    console.log('Hello plugin!');\n  },\n  answer: 42\n};\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/wechat-miniprogram-plugin/pages/hello-page.js",
    "content": "// pages/hello-page.js\nPage({\n\n  /**\n   * 页面的初始数据\n   */\n  data: {\n\n  },\n\n  /**\n   * 生命周期函数--监听页面加载\n   */\n  onLoad: function(options) {\n\n  },\n\n  /**\n   * 生命周期函数--监听页面初次渲染完成\n   */\n  onReady: function() {\n\n  },\n\n  /**\n   * 生命周期函数--监听页面显示\n   */\n  onShow: function() {\n\n  },\n\n  /**\n   * 生命周期函数--监听页面隐藏\n   */\n  onHide: function() {\n\n  },\n\n  /**\n   * 生命周期函数--监听页面卸载\n   */\n  onUnload: function() {\n\n  },\n\n  /**\n   * 页面相关事件处理函数--监听用户下拉动作\n   */\n  onPullDownRefresh: function() {\n\n  },\n\n  /**\n   * 页面上拉触底事件的处理函数\n   */\n  onReachBottom: function() {\n\n  },\n\n  /**\n   * 用户点击右上角分享\n   */\n  onShareAppMessage: function() {\n\n  }\n});\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/wechat-miniprogram-plugin/pages/hello-page.json",
    "content": "{\n  \"usingComponents\": {}\n}"
  },
  {
    "path": "examples/with-miniapp-plugin-component/wechat-miniprogram-plugin/pages/hello-page.wxml",
    "content": "<!--pages/hello-page.wxml-->\n<text>pages/hello-page.wxml</text>\n"
  },
  {
    "path": "examples/with-miniapp-plugin-component/wechat-miniprogram-plugin/pages/hello-page.wxss",
    "content": "/* pages/hello-page.wxss */"
  },
  {
    "path": "examples/with-miniapp-plugin-component/wechat-miniprogram-plugin/plugin.json",
    "content": "{\n  \"publicComponents\": {\n    \"hello-component\": \"components/hello-component\"\n  },\n  \"pages\": {\n    \"hello-page\": \"pages/hello-page\"\n  },\n  \"main\": \"index.js\"\n}"
  },
  {
    "path": "jest.config.js",
    "content": "// jest.config.js\n\n// Note: If you are using babel version 7 you have to install babel-jest with\n// yarn add --dev babel-jest @babel/core\n\nmodule.exports = {\n  'collectCoverage': true,\n  'verbose': true,\n  'setupFiles': [\n    './scripts/jest/setupEnvironment.js',\n    'jest-localstorage-mock'\n  ],\n  'setupFilesAfterEnv': ['./scripts/jest/setupTests.js'],\n  'moduleNameMapper': {\n    // https://jestjs.io/docs/en/webpack#handling-static-assets\n    // For CSS Modules\n    '\\\\.css$': '<rootDir>/scripts/jest/styleMock.js',\n  },\n  'testPathIgnorePatterns': [\n    '/node_modules/',\n    '/fixtures/',\n    '/__modules__/',\n    '/__files__/',\n    '/lib/',\n    '/dist/',\n    '/es/',\n  ]\n};\n"
  },
  {
    "path": "lerna.json",
    "content": "{\n  \"version\": \"1.7.0\",\n  \"npmClient\": \"ayarn\",\n  \"useWorkspaces\": true,\n  \"command\": {\n    \"bootstrap\": {\n      \"npmClientArgs\": [\"--no-lockfile\"]\n    }\n  },\n  \"packages\": [\n    \"packages/*\",\n    \"scripts/bench\"\n  ]\n}\n\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"private\": true,\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.12.9\",\n    \"@babel/plugin-proposal-class-properties\": \"^7.2.0\",\n    \"@babel/plugin-proposal-decorators\": \"^7.2.0\",\n    \"@babel/plugin-proposal-export-default-from\": \"^7.2.0\",\n    \"@babel/plugin-syntax-dynamic-import\": \"^7.7.4\",\n    \"@babel/plugin-transform-runtime\": \"^7.14.5\",\n    \"@babel/preset-env\": \"^7.2.0\",\n    \"@babel/preset-flow\": \"^7.0.0\",\n    \"@babel/preset-react\": \"^7.0.0\",\n    \"@rollup/plugin-babel\": \"^5.2.1\",\n    \"@rollup/plugin-commonjs\": \"^20.0.0\",\n    \"@rollup/plugin-node-resolve\": \"^13.0.0\",\n    \"@rollup/plugin-replace\": \"^2.3.4\",\n    \"@typescript-eslint/eslint-plugin\": \"^4.8.2\",\n    \"@typescript-eslint/parser\": \"^4.8.2\",\n    \"axios\": \"^0.21.1\",\n    \"babel-eslint\": \"^10.0.3\",\n    \"babel-jest\": \"^26.6.3\",\n    \"babel-loader\": \"^8.0.4\",\n    \"babel-merge\": \"^3.0.0\",\n    \"babel-plugin-transform-jsx-stylesheet\": \"0.6.5\",\n    \"chalk\": \"^2.4.1\",\n    \"chokidar\": \"^2.0.4\",\n    \"codecov\": \"^3.1.0\",\n    \"conventional-commit-types\": \"^2.2.0\",\n    \"cz-conventional-changelog\": \"^2.1.0\",\n    \"eslint\": \"^6.8.0\",\n    \"eslint-config-rax\": \"^0.1.0\",\n    \"eslint-plugin-import\": \"^2.22.1\",\n    \"eslint-plugin-module\": \"^0.1.0\",\n    \"eslint-plugin-react\": \"7.24.0\",\n    \"findup\": \"^0.1.5\",\n    \"ghooks\": \"^2.0.4\",\n    \"glob\": \"^7.1.3\",\n    \"gzip-size\": \"^5.0.0\",\n    \"istanbul-api\": \"^2.0.6\",\n    \"istanbul-lib-coverage\": \"^2.0.1\",\n    \"jest\": \"^26.6.3\",\n    \"jest-diff\": \"^26.6.2\",\n    \"jest-environment-node\": \"^26.6.2\",\n    \"jest-localstorage-mock\": \"^2.3.0\",\n    \"lerna\": \"^3.16.4\",\n    \"minimatch\": \"^3.0.4\",\n    \"minimist\": \"^1.2.0\",\n    \"rollup\": \"^2.33.3\",\n    \"rollup-plugin-terser\": \"^7.0.2\",\n    \"semver\": \"^7.1.0\",\n    \"semver-regex\": \"^2.0.0\",\n    \"typescript\": \"^4.0.0\",\n    \"uppercamelcase\": \"^3.0.0\",\n    \"webpack\": \"^4.27.1\"\n  },\n  \"scripts\": {\n    \"setup\": \"rm -rf node_modules && yarn install && npm run clean && npm run build\",\n    \"build:compile\": \"npm run clean:compile && npm run build:compile:packages\",\n    \"build:compile:packages\": \"node ./scripts/compile-packages.js\",\n    \"build:dist\": \"npm run clean:dist && node ./scripts/dist-core.js\",\n    \"build\": \"npm run build:compile && npm run build:dist\",\n    \"watch\": \"node ./scripts/compile-packages.js --watch\",\n    \"test\": \"npm run test:core\",\n    \"test:core\": \"jest --logHeapUsage --detectOpenHandles\",\n    \"lint\": \"eslint --cache --ext .js,.jsx ./\",\n    \"lint:fix\": \"eslint --cache --ext .js,.jsx --fix ./\",\n    \"coverage\": \"npm run test -- --coverage\",\n    \"coverage:upload\": \"npm run clean:coverage && npm run coverage && node ./scripts/mapCoverage.js && codecov\",\n    \"clean:dist\": \"rm -rf ./packages/*/dist\",\n    \"clean:compile\": \"rm -rf ./packages/*/lib && rm -rf ./packages/*/es\",\n    \"clean:coverage\": \"rm -rf ./coverage\",\n    \"clean:modules\": \"rm -rf ./packages/*/node_modules\",\n    \"clean\": \"jest --clearCache && lerna clean --yes && npm run clean:modules && npm run clean:compile && npm run clean:dist && npm run clean:coverage\",\n    \"clear\": \"git clean -xfd\",\n    \"bench\": \"cd scripts/bench && npm install && npm start\",\n    \"check-and-publish\": \"node ./scripts/check-and-publish\"\n  },\n  \"config\": {\n    \"ghooks\": {\n      \"commit-msg\": \"./scripts/validate-commit-msg.js\",\n      \"pre-commit\": \"npm run lint\"\n    },\n    \"commitizen\": {\n      \"path\": \"./node_modules/cz-conventional-changelog\"\n    }\n  },\n  \"workspaces\": [\n    \"packages/*\",\n    \"scripts/*\"\n  ]\n}\n"
  },
  {
    "path": "packages/driver-dom/CHANGELOG.md",
    "content": "## Changelog\n\n### v2.2.2\n\n- Fix hydrate style with webkit prefix in iOS 10\n\n### v2.2.1\n\n- Bump version\n\n### v2.2.0\n\n- Use `style-unit` convert `rpx`\n"
  },
  {
    "path": "packages/driver-dom/README.md",
    "content": "# driver-dom\n\n> DOM driver for Rax.\n\n## Install\n\n```bash\n$ npm install --save driver-dom\n```\n\n## Use\n\n```jsx\nimport {createElement, render} from 'rax';\nimport DriverDOM from 'driver-dom';\n\nfunction Example() {\n  return (\n    <div>\n      <img width=\"560\" height=\"560\" src=\"https://img.alicdn.com/tps/TB1z.55OFXXXXcLXXXXXXXXXXXX-560-560.jpg\" />\n    </div>\n  );\n}\n\nrender(<Example />, null, {\n  driver: DriverDOM\n});\n```\n\n## API\n\n**static setTagNamePrefix(prefix: String)**\n\nSet tag prefix for custom elements.\n\n```js\nimport DriverDOM from 'driver-dom';\n\nDriverDOM.setTagNamePrefix('a-');\n```\n\n\n\n\n"
  },
  {
    "path": "packages/driver-dom/package.json",
    "content": "{\n  \"name\": \"driver-dom\",\n  \"version\": \"2.2.2\",\n  \"description\": \"DOM driver for Rax\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"module\": \"es/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"dependencies\": {\n    \"style-unit\": \"^3.0.0\"\n  },\n  \"devDependencies\": {\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/driver-dom/src/__tests__/attributes.js",
    "content": "import { createElement, render } from 'rax';\nimport * as DriverDOM from '../';\n\ndescribe('attributes', () => {\n  let container;\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    (document.body || document.documentElement).appendChild(container);\n  });\n\n  describe('string properties', () => {\n    it('render string prop with simple numbers', () => {\n      render((\n        <div width={30} />\n      ), container, {\n        driver: DriverDOM\n      });\n\n      let node = container.children[0];\n      expect(node.getAttribute('width')).toBe('30');\n    });\n\n    it('render string prop with true value', () => {\n      render((\n        <a href={true} />\n      ), container, {\n        driver: DriverDOM\n      });\n\n      let node = container.children[0];\n      expect(node.getAttribute('href')).toBe('true');\n    });\n\n    it('render string prop with object value', () => {\n      render((\n        <input type=\"checkbox\" data={{foo: 'bar'}} />\n      ), container, {\n        driver: DriverDOM\n      });\n\n      let node = container.children[0];\n      expect(node.getAttribute('data')).toBe('[object Object]');\n    });\n  });\n\n  describe('boolean properties', () => {\n    it('render boolean prop with true value', () => {\n      render((\n        <div hidden={true} />\n      ), container, {\n        driver: DriverDOM\n      });\n\n      let node = container.children[0];\n      expect(node.getAttribute('hidden')).toBe('');\n    });\n\n    it('render boolean prop with false value', () => {\n      render((\n        <div hidden={false} />\n      ), container, {\n        driver: DriverDOM\n      });\n\n      let node = container.children[0];\n      expect(node.getAttribute('hidden')).toBe(null);\n    });\n\n    it('render boolean prop with self value', () => {\n      render((\n        <div hidden={'hidden'} />\n      ), container, {\n        driver: DriverDOM\n      });\n\n      let node = container.children[0];\n      expect(node.getAttribute('hidden')).toBe('');\n    });\n  });\n\n  describe('properties must set with property', () => {\n    it('render boolean prop with true', () => {\n      render((\n        <input type=\"checkbox\" checked={true} />\n      ), container, {\n        driver: DriverDOM\n      });\n\n      let node = container.children[0];\n      expect(node.checked).toBe(true);\n    });\n\n    it('render boolean prop with false', () => {\n      render((\n        <input type=\"checkbox\" checked={false} />\n      ), container, {\n        driver: DriverDOM\n      });\n\n      let node = container.children[0];\n      expect(node.checked).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/driver-dom/src/__tests__/css-custom-properties.js",
    "content": "import { createElement, render } from 'rax';\nimport * as DriverDOM from '../';\n\ndescribe('Support CSS custom properties', () => {\n  let container;\n  let logs;\n  const setProperty = CSSStyleDeclaration.prototype.setProperty;\n\n  beforeAll(() => {\n    CSSStyleDeclaration.prototype.setProperty = (prop, value) => {\n      logs.push([prop, value]);\n    };\n  });\n\n  afterAll(() => {\n    CSSStyleDeclaration.prototype.setProperty = setProperty;\n  });\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    (document.body || document.documentElement).appendChild(container);\n    logs = [];\n  });\n\n  it('CSS custom properties works.', () => {\n    render((\n      <div style={{\n        '--backgroundColor': 'red',\n        backgroundColor: 'var(--backgroundColor)',\n        width: '200px'\n      }}>\n        Test CSS custom properties.\n      </div>\n    ), container, {\n      driver: DriverDOM\n    });\n\n    expect(logs).toEqual([['--backgroundColor', 'red']]);\n  });\n});\n"
  },
  {
    "path": "packages/driver-dom/src/__tests__/css-unit-operations.js",
    "content": "import { createElement, render } from 'rax';\nimport * as DriverDOM from '../';\n\ndescribe('CSSPropertyOperations', () => {\n  let container;\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    (document.body || document.documentElement).appendChild(container);\n  });\n\n  it('should automatically append `px` to relevant styles', () => {\n    const styles = {\n      left: 0,\n      margin: 16,\n      opacity: 0.5,\n      padding: '4px',\n    };\n    render(<div style={styles} />, container, { driver: DriverDOM });\n\n    const targetNode = container.children[0];\n    expect(targetNode.style._values).toMatchObject({ 'left': '0px', 'opacity': '0.5', 'margin': '16px', 'padding': '4px' });\n  });\n\n  it('should not append `px` to styles that might need a number', () => {\n    const styles = {\n      flex: 1,\n      flexGrow: 0,\n      lineHeight: 1.1,\n      opacity: 0.5,\n    };\n    render(<div style={styles} />, container, { driver: DriverDOM });\n\n    const targetNode = container.children[0];\n    expect(targetNode.style._values).toMatchObject({ 'flex': '1', 'opacity': '0.5', 'flex-grow': '0', 'line-height': 1.1 });\n  });\n\n  it('should translate `rpx` to the `vw` relative to the width of the 750 screen', () => {\n    const styles = {\n      width: '375rpx',\n      height: '150rpx',\n      margin: '75rpx 100vh'\n    };\n    render(<div style={styles} />, container, { driver: DriverDOM });\n\n    const targetNode = container.children[0];\n    expect(targetNode.style._values).toMatchObject({ 'width': '50vw', 'height': '20vw', 'margin': '10vw 100vh' });\n  });\n\n  it('should not change the style values order after hydration', () => {\n    container.innerHTML = '<div style=\"font-size: 14px; display: flex; flex-direction: row;\"></div>';\n\n    const styles = {\n      fontSize: '14px',\n      display: 'flex',\n      flexDirection: 'row'\n    };\n\n    render(<div style={styles} />, container, { driver: DriverDOM, hydrate: true });\n\n    const targetNode = container.children[0];\n    expect(JSON.stringify(targetNode.style._values)).toEqual(JSON.stringify({\n      'font-size': '14px',\n      'display': 'flex',\n      'flex-direction': 'row'\n    }));\n  });\n\n  it('should not translate `rpx` to the `vw` with url()', () => {\n    const styles = {\n      width: '375rpx',\n      height: '150rpx',\n      backgroundImage: 'url(\"abc2rpx\")'\n    };\n    render(<div style={styles} />, container, { driver: DriverDOM });\n\n    const targetNode = container.children[0];\n    expect(targetNode.style._values).toMatchObject({ 'width': '50vw', 'height': '20vw', 'background-image': 'url(abc2rpx)' });\n  });\n});\n"
  },
  {
    "path": "packages/driver-dom/src/__tests__/event-listener.js",
    "content": "import { createElement, render } from 'rax';\nimport * as DriverDOM from '../';\n\ndescribe('EventListener', () => {\n  let container;\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    (document.body || document.documentElement).appendChild(container);\n  });\n\n  it('should dispatch events', () => {\n    const mock = jest.fn();\n\n    render(<div onClick={mock} />, container, { driver: DriverDOM });\n\n    const targetNode = container.children[0];\n    targetNode.dispatchEvent(\n      new MouseEvent('click', {\n        bubbles: true,\n      }),\n    );\n\n    expect(mock).toBeCalled();\n  });\n});\n"
  },
  {
    "path": "packages/driver-dom/src/__tests__/hydrate.js",
    "content": "import { createElement, render, useEffect } from 'rax';\n\ndescribe('Hydrate', () => {\n  let DriverDOM;\n  let container;\n\n  beforeEach(() => {\n    jest.resetModules();\n    DriverDOM = require('../');\n\n    jest.useFakeTimers();\n    container = document.createElement('div');\n    container.innerHTML = '<div class=\"container\"><div>About Rax</div><div>Docs</div></div>';\n    (document.body || document.documentElement).appendChild(container);\n  });\n\n  it('should keep comment node when rendering multi adjacent text nodes', () => {\n    container = document.createElement('div');\n    container.innerHTML = '<div>About:<!--|-->Rax</div>';\n    (document.body || document.documentElement).appendChild(container);\n\n    const Component = (props) => {\n      return (\n        <div>About:{props.name}</div>\n      );\n    };\n\n    render(<Component name=\"Rax\" />, container, { driver: DriverDOM, hydrate: true });\n    jest.runAllTimers();\n\n    expect(container.childNodes[0].childNodes[0].data).toBe('About:');\n    expect(container.childNodes[0].childNodes[1].nodeType).toBe(8); // comment\n    expect(container.childNodes[0].childNodes[2].data).toBe('Rax');\n  });\n\n  it('should not be affected by render in useEffect', () => {\n    const childContainer = document.createElement('div');\n    (document.body || document.documentElement).appendChild(childContainer);\n\n    const Child = () => {\n      useEffect(() => {\n        render(<span>child content</span>, childContainer);\n      });\n\n      return null;\n    };\n\n    const Component = () => {\n      return (\n        <div class=\"container\">\n          <div>About Rax</div>\n          <Child />\n        </div>\n      );\n    };\n\n    jest.useFakeTimers();\n\n    render(<Component />, container, { driver: DriverDOM, hydrate: true });\n\n    jest.runAllTimers();\n\n    expect(container.childNodes[0].childNodes[1].nodeType).toBe(8); // comment;\n  });\n\n  it('should throw error for nested render when hydrating', () => {\n    const childContainer = document.createElement('div');\n    (document.body || document.documentElement).appendChild(childContainer);\n\n    const Child = () => {\n      render(<span>child content</span>, childContainer);\n      return null;\n    };\n\n    const Component = () => {\n      return (\n        <div class=\"container\">\n          <div>About Rax</div>\n          <Child />\n        </div>\n      );\n    };\n\n    expect(() => {\n      jest.useFakeTimers();\n\n      render(<Component />, container, { driver: DriverDOM, hydrate: true });\n\n      jest.runAllTimers();\n    }).toThrowError('Nested render is not allowed when hydrating. If necessary, trigger render in useEffect.', {\n      withoutStack: true,\n    });\n  });\n\n  it('should warn for replaced hydratable element', () => {\n    const Component = () => {\n      return (\n        <div className=\"container\">\n          <img src=\"./logo.png\" />\n          <div>About Rax</div>\n          <div>Docs</div>\n        </div>\n      );\n    };\n\n    expect(() => {\n      render(<Component />, container, { driver: DriverDOM, hydrate: true });\n\n      jest.runAllTimers();\n    }).toWarnDev('Warning: Expected server HTML to contain a matching <img> in <div.container>, but got <div>', {\n      withoutStack: true,\n    });\n\n    expect(container.childNodes[0].childNodes[0].tagName).toBe('IMG');\n  });\n\n  it('should not warn for replaced comment', () => {\n    container = document.createElement('div');\n    container.innerHTML = '<div><!-- --><div>About Rax</div><div>Docs</div></div>';\n    (document.body || document.documentElement).appendChild(container);\n\n    const Component = () => {\n      return (\n        <div class=\"container\">\n          <img src=\"./logo.png\" />\n          <div>About Rax</div>\n          <div>Docs</div>\n        </div>\n      );\n    };\n\n    render(<Component />, container, { driver: DriverDOM, hydrate: true });\n    jest.runAllTimers();\n\n    expect(container.childNodes[0].childNodes[0].tagName).toBe('IMG');\n  });\n\n  it('should warn for deleted hydratable element', () => {\n    const Component = () => {\n      return (\n        <div class=\"container\">\n          <div>About Rax</div>\n        </div>\n      );\n    };\n\n    expect(() => {\n      jest.useFakeTimers();\n      render(<Component />, container, { driver: DriverDOM, hydrate: true });\n\n      jest.runAllTimers();\n    }).toWarnDev('Warning: Did not expect server HTML to contain a <div> in <div.container>', {\n      withoutStack: true,\n    });\n\n    expect(container.childNodes[0].childNodes[1]).toBe(undefined);\n  });\n\n  it('should warn for inserted Hydrated element', () => {\n    const Component = () => {\n      return (\n        <div className=\"container\">\n          <div>About Rax</div>\n          <div>Docs</div>\n          <div className=\"example\">Examples</div>\n        </div>\n      );\n    };\n\n    expect(() => {\n      render(<Component />, container, { driver: DriverDOM, hydrate: true });\n\n      jest.runAllTimers();\n    }).toWarnDev('Warning: Expected server HTML to contain a matching <div> in <div.container>', {\n      withoutStack: true,\n    });\n\n    expect(container.childNodes[0].childNodes[2].tagName).toBe('DIV');\n  });\n\n  it('should not compare and delete hydration child with innerHTML', () => {\n    const Component = () => {\n      return (\n        <div className=\"container\" dangerouslySetInnerHTML={{__html: '<div>About Rax</div><div>Docs</div>'}} />\n      );\n    };\n\n    render(<Component />, container, { driver: DriverDOM, hydrate: true });\n\n    jest.runAllTimers();\n\n    expect(container.childNodes[0].childNodes[0].tagName).toBe('DIV');\n  });\n});\n"
  },
  {
    "path": "packages/driver-dom/src/__tests__/node-operations.js",
    "content": "import { createElement, Fragment, render, useState } from 'rax';\nimport * as DriverDOM from '../';\n\ndescribe('NodeOperations', () => {\n  let container;\n  let updateHandler;\n\n  beforeEach(() => {\n    jest.useFakeTimers();\n    container = document.createElement('div');\n    (document.body || document.documentElement).appendChild(container);\n  });\n\n  it('should append child', () => {\n    const Component = () => {\n      const [temp, setTemp] = useState(false);\n      updateHandler = setTemp;\n      return <Fragment>{temp ? <div /> : null}</Fragment>;\n    };\n\n    render(<Component />, container, { driver: DriverDOM });\n\n    updateHandler(true);\n    jest.runAllTimers();\n    expect(container.childNodes[0].tagName).toBe('DIV');\n  });\n\n  it('should update text', () => {\n    const Component = () => {\n      const [temp, setTemp] = useState('');\n      updateHandler = setTemp;\n      return <p>{temp}</p>;\n    };\n\n    render(<Component />, container, { driver: DriverDOM });\n\n    updateHandler('hello');\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toBe('hello');\n  });\n\n  it('should removeAttribute className', () => {\n    const Component = () => {\n      const [temp, setTemp] = useState(true);\n      updateHandler = setTemp;\n      return <div {...(temp ? { className: 'hello' } : {})} />;\n    };\n\n    render(<Component />, container, { driver: DriverDOM });\n\n    updateHandler(false);\n    jest.runAllTimers();\n    expect(container.childNodes[0].className).toBe('');\n  });\n});\n"
  },
  {
    "path": "packages/driver-dom/src/__tests__/svg.js",
    "content": "import { createElement, render } from 'rax';\nimport * as DriverDOM from '../';\n\ndescribe('svg', () => {\n  let container;\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    (document.body || document.documentElement).appendChild(container);\n  });\n\n  it('should create SVG with SVG namespace URI', () => {\n    render((\n      <svg height=\"90\" width=\"200\">\n        <text x=\"10\" y=\"20\" style={{ fill: 'red' }}>\n          <tspan x=\"10\" y=\"45\">First line.</tspan>\n          <tspan x=\"10\" y=\"70\">Second line.</tspan>\n        </text>\n        Sorry, your browser does not support inline SVG.\n      </svg>\n    ), container, {\n      driver: DriverDOM\n    });\n    let svgNode = container.children[0];\n    expect(svgNode.namespaceURI).toEqual('http://www.w3.org/2000/svg');\n\n    let textNode = svgNode.children[0];\n    expect(textNode.namespaceURI).toEqual('http://www.w3.org/2000/svg');\n\n    let tspanNode = textNode.children[0];\n    expect(tspanNode.namespaceURI).toEqual('http://www.w3.org/2000/svg');\n  });\n\n  it('should set transform as attribute', () => {\n    render((\n      <svg height=\"90\" width=\"200\">\n        <text transform=\"scale(1 0.5)\" test={true}>\n          <tspan x=\"10\" y=\"45\">First line.</tspan>\n        </text>\n        Sorry, your browser does not support inline SVG.\n      </svg>\n    ), container, {\n      driver: DriverDOM\n    });\n\n    let svgNode = container.children[0];\n    let textNode = svgNode.children[0];\n\n    expect(textNode.getAttribute('transform')).toEqual('scale(1 0.5)');\n  });\n});\n"
  },
  {
    "path": "packages/driver-dom/src/index.d.ts",
    "content": "// Driver spec: https://github.com/alibaba/rax/blob/master/docs/en-US/driver-spec.md\ndeclare namespace Driver {\n  function createBody(): void;\n  function createEmpty(component: any): void;\n  function createText(): void;\n  function updateText(node: any, text: any)\n  function createElement(type: any, props: any, component: any)\n  function appendChild(node: any, parent: any)\n  function removeChild(node: any, parent: any)\n  function replaceChild(newChild: any, oldChild: any, parent: any)\n  function insertAfter(node: any, after: any, parent: any)\n  function insertBefore(node: any, before: any, parent: any)\n  function addEventListener(node: any, eventName: any, eventHandler: any)\n  function removeEventListener(node: any, eventName: any, eventHandler: any)\n  function setAttribute(node: any, propKey: any, propValue: any)\n  function removeAttribute(node: any, propKey: any)\n  function setStyle(node: any, styleObject: any)\n}\n\nexport default Driver;\n"
  },
  {
    "path": "packages/driver-dom/src/index.js",
    "content": "/**\n * Driver for Web DOM\n **/\nimport { convertUnit, setViewportWidth, setUnitPrecision, cached } from 'style-unit';\nimport {\n  warnForReplacedHydratebleElement,\n  warnForDeletedHydratableElement,\n  warnForInsertedHydratedElement\n} from './warning';\n\n// opacity -> opa\n// fontWeight -> ntw\n// lineHeight|lineClamp -> ne[ch]\n// flex|flexGrow|flexPositive|flexShrink|flexNegative|boxFlex|boxFlexGroup|zIndex -> ex(?:s|g|n|p|$)\n// order -> ^ord\n// zoom -> zoo\n// gridArea|gridRow|gridRowEnd|gridRowSpan|gridRowStart|gridColumn|gridColumnEnd|gridColumnSpan|gridColumnStart -> grid\n// columnCount -> mnc\n// tabSize -> bs\n// orphans -> orp\n// windows -> ows\n// animationIterationCount -> onit\n// borderImageOutset|borderImageSlice|borderImageWidth -> erim\nconst NON_DIMENSIONAL_REG = /opa|ntw|ne[ch]|ex(?:s|g|n|p|$)|^ord|zoo|grid|orp|ows|mnc|^columns$|bs|erim|onit/i;\nconst EVENT_PREFIX_REG = /^on[A-Z]/;\nconst DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';\nconst HTML = '__html';\nconst INNER_HTML = 'innerHTML';\nconst CLASS_NAME = 'className';\nconst CLASS = 'class';\nconst STYLE = 'style';\nconst CHILDREN = 'children';\nconst TEXT_CONTENT_ATTR = 'textContent';\nconst CREATE_ELEMENT = 'createElement';\nconst CREATE_COMMENT = 'createComment';\nconst CREATE_TEXT_NODE = 'createTextNode';\nconst SET_ATTRIBUTE = 'setAttribute';\nconst REMOVE_ATTRIBUTE = 'removeAttribute';\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst TEXT_NODE = 3;\nconst COMMENT_NODE = 8;\nconst TEXT_SPLIT_COMMENT = '|';\nconst EMPTY = '';\nconst HYDRATION_INDEX = '__i';\nconst HYDRATION_APPEND = '__a';\nconst WITH_INNERHTML = '__h';\nconst __DEV__ = process.env.NODE_ENV !== 'production';\n\nlet tagNamePrefix = EMPTY;\n// Flag indicating if the diff is currently within an SVG\nlet isSVGMode = false;\nlet isHydrating = false;\n\n/**\n * Camelize CSS property.\n * Vendor prefixes should begin with a capital letter.\n * For example:\n * background-color -> backgroundColor\n * -webkit-transition -> webkitTransition\n */\nconst camelizeStyleName = cached(name => {\n  return name\n    .replace(/-([a-z])/gi, function(s, g) {\n      return g.toUpperCase();\n    });\n});\n\nconst isDimensionalProp = cached(prop => !NON_DIMENSIONAL_REG.test(prop));\nconst isEventProp = cached(prop => EVENT_PREFIX_REG.test(prop));\n\nexport function setTagNamePrefix(prefix) {\n  tagNamePrefix = prefix;\n}\n\nexport function createBody() {\n  return document.body;\n}\n\nexport function createEmpty(component) {\n  const parent = component._parent;\n  let node;\n\n  if (isHydrating) {\n    const hydrationChild = findHydrationChild(parent);\n\n    if (hydrationChild) {\n      if (hydrationChild.nodeType === COMMENT_NODE) {\n        return hydrationChild;\n      } else {\n        node = document[CREATE_COMMENT](EMPTY);\n        replaceChild(node, hydrationChild, parent);\n      }\n    } else {\n      node = document[CREATE_COMMENT](EMPTY);\n      node[HYDRATION_APPEND] = true;\n    }\n  } else {\n    node = document[CREATE_COMMENT](EMPTY);\n  }\n\n  return node;\n}\n\nexport function createText(text, component) {\n  const parent = component._parent;\n  let node;\n\n  if (isHydrating) {\n    const hydrationChild = findHydrationChild(parent);\n\n    if (hydrationChild) {\n      if (hydrationChild.nodeType === TEXT_NODE) {\n        if (text !== hydrationChild[TEXT_CONTENT_ATTR]) {\n          hydrationChild[TEXT_CONTENT_ATTR] = text;\n        }\n        return hydrationChild;\n      } else {\n        node = document[CREATE_TEXT_NODE](text);\n        replaceChild(node, hydrationChild, parent);\n      }\n    } else {\n      node = document[CREATE_TEXT_NODE](text);\n      node[HYDRATION_APPEND] = true;\n    }\n  } else {\n    node = document[CREATE_TEXT_NODE](text);\n  }\n\n  return node;\n}\n\nexport function updateText(node, text) {\n  node[TEXT_CONTENT_ATTR] = text;\n}\n\nfunction findHydrationChild(parent) {\n  const childNodes = parent.childNodes;\n\n  if (parent[HYDRATION_INDEX] == null) {\n    parent[HYDRATION_INDEX] = 0;\n  }\n\n  const child = childNodes[parent[HYDRATION_INDEX]++];\n\n  // If child is an comment node for spliting text node, use the next node.\n  if (child && child.nodeType === COMMENT_NODE && child.data === TEXT_SPLIT_COMMENT) {\n    return childNodes[parent[HYDRATION_INDEX]++];\n  } else {\n    return child;\n  }\n}\n\n/**\n * @param {string} type node type\n * @param {object} props elemement properties\n * @param {object} component component instance\n * @param {boolean} __shouldConvertUnitlessToRpx should add unit when missing\n */\nexport function createElement(type, props, component, __shouldConvertUnitlessToRpx) {\n  const parent = component._parent;\n  isSVGMode = type === 'svg' || parent && parent.namespaceURI === SVG_NS;\n  let node;\n  let hydrationChild = null;\n\n  function createNode() {\n    if (isSVGMode) {\n      node = document.createElementNS(SVG_NS, type);\n    } else if (tagNamePrefix) {\n      let tagNamePrefix = typeof tagNamePrefix === 'function' ? tagNamePrefix(type) : tagNamePrefix;\n      node = document[CREATE_ELEMENT](tagNamePrefix + type);\n    } else {\n      node = document[CREATE_ELEMENT](type);\n    }\n  }\n\n  if (isHydrating) {\n    hydrationChild = findHydrationChild(parent);\n\n    if (hydrationChild) {\n      if (type === hydrationChild.nodeName.toLowerCase()) {\n        for (let attributes = hydrationChild.attributes, i = attributes.length; i--;) {\n          const attribute = attributes[i];\n          const attributeName = attribute.name;\n          const propValue = props[attributeName];\n\n          if (\n            // The class or className prop all not in props\n            attributeName === CLASS && props[CLASS_NAME] == null && propValue == null ||\n            // The style prop is empty object or not in props\n            attributeName === STYLE && (propValue == null || Object.keys(propValue).length === 0) ||\n            // Remove rendered node attribute that not existed\n            attributeName !== CLASS && attributeName !== STYLE && propValue == null\n          ) {\n            hydrationChild[REMOVE_ATTRIBUTE](attributeName);\n            continue;\n          }\n\n          if (attributeName === STYLE) {\n            // Remove invalid style prop, and direct reset style to child avoid diff style\n            // Set style to empty will change the index of style, so here need to traverse style backwards\n            for (let l = hydrationChild.style.length; 0 < l; l--) {\n              // Prop name get from node style is hyphenated, eg: background-color\n              const stylePropName = hydrationChild.style[l - 1];\n              // Style with webkit prefix, will cause stylePropName be undefined in iOS 10.1 and 10.2.\n              // Eg. when set transition-timing-function to be empty, it will also delete -webkit-transition-timing-function.\n              if (stylePropName) {\n                const camelizedStyleName = camelizeStyleName(stylePropName);\n                if (propValue[camelizedStyleName] == null) {\n                  hydrationChild.style[camelizedStyleName] = EMPTY;\n                }\n              }\n            }\n          }\n        }\n\n        node = hydrationChild;\n      } else {\n        createNode();\n        replaceChild(node, hydrationChild, parent);\n        if (__DEV__) {\n          warnForReplacedHydratebleElement(parent, node, hydrationChild);\n        }\n      }\n    } else {\n      createNode();\n      node[HYDRATION_APPEND] = true;\n      if (__DEV__) {\n        warnForInsertedHydratedElement(parent, node);\n      }\n    }\n  } else {\n    createNode();\n  }\n\n  for (let prop in props) {\n    const value = props[prop];\n    if (prop === CHILDREN) continue;\n\n    if (value != null) {\n      if (prop === STYLE) {\n        setStyle(node, value, __shouldConvertUnitlessToRpx);\n      } else if (isEventProp(prop)) {\n        addEventListener(node, prop.slice(2).toLowerCase(), value, component);\n      } else {\n        setAttribute(node, prop, value, isSVGMode);\n      }\n    }\n  }\n\n  return node;\n}\n\nexport function appendChild(node, parent) {\n  if (!isHydrating || node[HYDRATION_APPEND]) {\n    return parent.appendChild(node);\n  }\n}\n\nexport function removeChild(node, parent) {\n  parent = parent || node.parentNode;\n  // Maybe has been removed when remove child\n  if (parent) {\n    parent.removeChild(node);\n  }\n}\n\nexport function replaceChild(newChild, oldChild, parent) {\n  parent = parent || oldChild.parentNode;\n  parent.replaceChild(newChild, oldChild);\n}\n\nexport function insertAfter(node, after, parent) {\n  parent = parent || after.parentNode;\n  const nextSibling = after.nextSibling;\n  if (nextSibling) {\n    // Performance improve when node has been existed before nextSibling\n    if (nextSibling !== node) {\n      insertBefore(node, nextSibling, parent);\n    }\n  } else {\n    appendChild(node, parent);\n  }\n}\n\nexport function insertBefore(node, before, parent) {\n  parent = parent || before.parentNode;\n  parent.insertBefore(node, before);\n}\n\nexport function addEventListener(node, eventName, eventHandler) {\n  return node.addEventListener(eventName, eventHandler);\n}\n\nexport function removeEventListener(node, eventName, eventHandler) {\n  return node.removeEventListener(eventName, eventHandler);\n}\n\nexport function removeAttribute(node, propKey) {\n  if (propKey === DANGEROUSLY_SET_INNER_HTML) {\n    return node[INNER_HTML] = null;\n  }\n\n  if (propKey === CLASS_NAME) propKey = CLASS;\n\n  if (propKey in node) {\n    try {\n      // Some node property is readonly when in strict mode\n      node[propKey] = null;\n    } catch (e) { }\n  }\n\n  node[REMOVE_ATTRIBUTE](propKey);\n}\n\nexport function setAttribute(node, propKey, propValue, isSvg) {\n  if (propKey === DANGEROUSLY_SET_INNER_HTML) {\n    // For reduce innerHTML operation to improve performance.\n    if (node[INNER_HTML] !== propValue[HTML]) {\n      node[INNER_HTML] = propValue[HTML];\n    }\n\n    node[WITH_INNERHTML] = true;\n    return;\n  }\n\n  if (propKey === CLASS_NAME) propKey = CLASS;\n\n  // Prop for svg can only be set by attribute\n  if (!isSvg && propKey in node) {\n    try {\n      // Some node property is readonly when in strict mode\n      node[propKey] = propValue;\n    } catch (e) {\n      node[SET_ATTRIBUTE](propKey, propValue);\n    }\n  } else {\n    node[SET_ATTRIBUTE](propKey, propValue);\n  }\n}\n\n/**\n * @param {object} node target node\n * @param {object} style target node style value\n * @param {boolean} __shouldConvertUnitlessToRpx\n */\nexport function setStyle(node, style, __shouldConvertUnitlessToRpx) {\n  for (let prop in style) {\n    const value = style[prop];\n    let convertedValue;\n\n    if (typeof value === 'number' && isDimensionalProp(prop)) {\n      if (__shouldConvertUnitlessToRpx) {\n        convertedValue = value + 'rpx';\n        // Transfrom rpx to vw\n        convertedValue = convertUnit(convertedValue);\n      } else {\n        convertedValue = value + 'px';\n      }\n    } else {\n      convertedValue = convertUnit(value);\n    }\n\n    // Support CSS custom properties (variables) like { --main-color: \"black\" }\n    if (prop[0] === '-' && prop[1] === '-') {\n      // reference: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/setProperty.\n      // style.setProperty do not support Camel-Case style properties.\n      node.style.setProperty(prop, convertedValue);\n    } else {\n      node.style[prop] = convertedValue;\n    }\n  }\n}\n\nexport function beforeRender({ hydrate }) {\n  // Nested render may reset `isHydrating`, `recolectHydrationChild` will not work correctly after render.\n  if (isHydrating && !hydrate) {\n    if (__DEV__) {\n      throw new Error(\n        'Nested render is not allowed when hydrating. ' +\n        'If necessary, trigger render in useEffect.'\n      );\n    } else {\n      throw new Error('Nested render found.');\n    }\n  }\n\n  isHydrating = hydrate;\n}\n\nfunction recolectHydrationChild(hydrationParent) {\n  // Should not to compare node with dangerouslySetInnerHTML because vdomLength is alway 0\n  if (hydrationParent[WITH_INNERHTML]) {\n    return;\n  }\n\n  const nativeLength = hydrationParent.childNodes.length;\n  const vdomLength = hydrationParent[HYDRATION_INDEX] || 0;\n  if (nativeLength - vdomLength > 0) {\n    for (let i = nativeLength - 1; i >= vdomLength; i--) {\n      if (__DEV__) {\n        warnForDeletedHydratableElement(hydrationParent, hydrationParent.childNodes[i]);\n      }\n      hydrationParent.removeChild(hydrationParent.childNodes[i]);\n    }\n  }\n\n  for (let j = hydrationParent.childNodes.length - 1; j >= 0; j--) {\n    recolectHydrationChild(hydrationParent.childNodes[j]);\n  }\n}\n\nexport function afterRender({ container }) {\n  if (isHydrating) {\n    // Remove native node when more then vdom node\n    recolectHydrationChild(container);\n    isHydrating = false;\n  }\n}\n\n/**\n * Remove all children from node.\n * @NOTE: Optimization at web.\n */\nexport function removeChildren(node) {\n  node.textContent = EMPTY;\n}\n\nexport {\n  /**\n   * Set viewport width.\n   * @param viewport {Number} Viewport width, default to 750.\n  */\n  setViewportWidth,\n  /**\n   * Set unit precision.\n   * @param n {Number} Unit precision, default to 4.\n   */\n  setUnitPrecision\n};\n"
  },
  {
    "path": "packages/driver-dom/src/warning.js",
    "content": "let didWarnInvalidHydration = false;\n\nconst __DEV__ = process.env.NODE_ENV !== 'production';\n\nexport function warnForReplacedHydratebleElement(\n  parentNode,\n  clientNode,\n  serverNode,\n) {\n  if (__DEV__) {\n    if (didWarnInvalidHydration) {\n      return;\n    }\n\n    // should not warn for replace comment, bescause it may be a placeholder from server\n    if (serverNode.nodeType === 8) {\n      return;\n    }\n\n    didWarnInvalidHydration = true;\n    warning(\n      'Expected server HTML to contain a matching %s in %s, but got %s.',\n      getNodeName(clientNode),\n      getNodeName(parentNode),\n      getNodeName(serverNode)\n    );\n  }\n}\n\nexport function warnForDeletedHydratableElement(\n  parentNode,\n  child,\n) {\n  if (__DEV__) {\n    if (didWarnInvalidHydration) {\n      return;\n    }\n\n    didWarnInvalidHydration = true;\n\n    warning(\n      'Did not expect server HTML to contain a %s in %s.',\n      getNodeName(child),\n      getNodeName(parentNode),\n    );\n  }\n}\n\nexport function warnForInsertedHydratedElement(\n  parentNode,\n  node\n) {\n  if (__DEV__) {\n    if (didWarnInvalidHydration) {\n      return;\n    }\n\n    didWarnInvalidHydration = true;\n\n    warning(\n      'Expected server HTML to contain a matching %s in %s.',\n      getNodeName(node),\n      getNodeName(parentNode),\n    );\n  }\n}\n\n/**\n * Concat tagName、 id and class info to help locate a node\n * @param {*} node HTMLElement\n * @returns {string} for example: <div#home.rax-view.home>\n */\nfunction getNodeName(node) {\n  // text node don`t have tagName\n  if (!node.tagName) {\n    return node.nodeName;\n  }\n\n  const name = node.tagName.toLowerCase();\n  const id = node.id ? '#' + node.id : '';\n  const classStr = node.className || '';\n  const classList = classStr.split(' ').map((className) => {\n    return className ? '.' + className : '';\n  });\n\n  return `<${name}${id}${classList.join('')}>`;\n}\n\nexport let warning = () => {};\n\nif (process.env.NODE_ENV !== 'production') {\n  warning = (template, ...args) => {\n    if (typeof console !== 'undefined') {\n      let argsWithFormat = args.map(item => '' + item);\n      argsWithFormat.unshift('Warning: ' + template);\n      // Don't use spread (or .apply) directly because it breaks IE9\n      Function.prototype.apply.call(console.error, console, argsWithFormat);\n    }\n\n    // For works in DevTools when enable `Pause on caught exceptions`\n    // that can find the component where caused this warning\n    try {\n      let argIndex = 0;\n      const message = 'Warning: ' + template.replace(/%s/g, () => args[argIndex++]);\n      throw new Error(message);\n    } catch (e) {}\n  };\n}\n"
  },
  {
    "path": "packages/driver-server/README.md",
    "content": "# driver-server\n\n> Server driver for Rax.\n\n## Install\n\n```bash\n$ npm install --save driver-server\n```\n\n## Use\n\n```jsx\nimport {createElement, Component, render} from 'rax';\nimport ServerDriver from 'driver-server';\nimport {isNode} from 'universal-env';\n\nclass Example extends Component {\n  render() {\n    return (\n      <div>\n        <img width=\"560\" height=\"560\" src=\"https://img.alicdn.com/tps/TB1z.55OFXXXXcLXXXXXXXXXXXX-560-560.jpg\" />\n      </div>\n    );\n  }\n}\n\nrender(<Example />, null, {\n  driver: isNode ? ServerDriver : null\n});\n```\n"
  },
  {
    "path": "packages/driver-server/package.json",
    "content": "{\n  \"name\": \"driver-server\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Server driver for Rax\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\"\n}\n"
  },
  {
    "path": "packages/driver-server/src/index.js",
    "content": "/**\n *  Server driver\n **/\nconst ID = 'id';\nconst STYLE = 'style';\nconst CHILDREN = 'children';\nconst DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';\nconst EVENT_PREFIX_REGEXP = /^on[A-Z]/;\n\nconst ELEMENT_NODE = 1;\nconst TEXT_NODE = 3;\nconst COMMENT_NODE = 8;\n\nconst Driver = {\n  // Internal state\n  nodeMaps: {},\n\n  getElementById(id) {\n    return this.nodeMaps[id];\n  },\n\n  createBody() {\n    return {\n      nodeType: ELEMENT_NODE,\n      tagName: 'BODY',\n      attributes: {},\n      style: {},\n      eventListeners: {},\n      childNodes: [],\n      parentNode: null\n    };\n  },\n\n  createComment(content) {\n    return {\n      nodeType: COMMENT_NODE,\n      data: content,\n      parentNode: null\n    };\n  },\n\n  createEmpty() {\n    return this.createComment(' empty ');\n  },\n\n  createText(text) {\n    return {\n      nodeType: TEXT_NODE,\n      data: text,\n      parentNode: null\n    };\n  },\n\n  updateText(node, text) {\n    node.data = text;\n  },\n\n  createElement(type, props) {\n    let node = {\n      nodeType: ELEMENT_NODE,\n      tagName: type.toUpperCase(),\n      attributes: {},\n      style: props.style || {},\n      eventListeners: {},\n      childNodes: [],\n      parentNode: null\n    };\n\n    this.setNativeProps(node, props, true);\n\n    return node;\n  },\n\n  appendChild(node, parent) {\n    parent.childNodes.push(node);\n    node.parentNode = parent;\n  },\n\n  removeChild(node, parent) {\n    parent = parent || node.parentNode;\n    let id = node.attributes && node.attributes[ID];\n    if (id != null) {\n      this.nodeMaps[id] = null;\n    }\n    if (node.parentNode) {\n      let idx = node.parentNode.childNodes.indexOf(node);\n      node.parentNode.childNodes.splice(idx, 1);\n      node.parentNode = null;\n    }\n  },\n\n  replaceChild(newChild, oldChild, parent) {\n    parent = parent || oldChild.parentNode;\n    let previousSibling = this.previousSibling(oldChild);\n    let nextSibling = this.nextSibling(oldChild);\n\n    this.removeChild(oldChild, parent);\n    if (previousSibling) {\n      this.insertAfter(newChild, previousSibling, parent);\n    } else if (nextSibling) {\n      this.insertBefore(newChild, nextSibling, parent);\n    } else {\n      this.appendChild(newChild, parent);\n    }\n  },\n\n  insertAfter(node, after, parent) {\n    parent = parent || after.parentNode;\n    let nodeIdx = parent.childNodes.indexOf(node);\n    if (nodeIdx !== -1) {\n      parent.childNodes.splice(nodeIdx, 1);\n    }\n\n    let idx = parent.childNodes.indexOf(after);\n\n    if (idx === parent.childNodes.length - 1) {\n      parent.childNodes.push(node);\n    } else {\n      parent.childNodes.splice(idx + 1, 0, node);\n    }\n    node.parentNode = parent;\n  },\n\n  insertBefore(node, before, parent) {\n    parent = parent || before.parentNode;\n    let nodeIdx = parent.childNodes.indexOf(node);\n    if (nodeIdx !== -1) {\n      parent.childNodes.splice(nodeIdx, 1);\n    }\n\n    let idx = parent.childNodes.indexOf(before);\n    parent.childNodes.splice(idx, 0, node);\n    node.parentNode = parent;\n  },\n\n  nextSibling(node) {\n    let parentNode = node.parentNode;\n    if (parentNode) {\n      let idx = parentNode.childNodes.indexOf(node);\n      return parentNode.childNodes[idx + 1];\n    }\n  },\n\n  previousSibling(node) {\n    let parentNode = node.parentNode;\n    if (parentNode) {\n      let idx = parentNode.childNodes.indexOf(node);\n      return parentNode.childNodes[idx - 1];\n    }\n  },\n\n  addEventListener(node, eventName, eventHandler) {\n    node.eventListeners[eventName] = eventHandler;\n  },\n\n  removeEventListener(node, eventName, eventHandler) {\n    delete node.eventListeners[eventName];\n  },\n\n  removeAttribute(node, propKey, propValue) {\n    if (propKey === 'className') {\n      propKey = 'class';\n    }\n\n    if (propKey == ID) {\n      this.nodeMaps[propValue] = null;\n    }\n\n    if (node.tagName === 'INPUT' &&\n      ( propKey == 'checked' && (node.attributes.type === 'checkbox' || node.attributes.type === 'radio')\n      || propKey == 'value')) {\n      node.attributes[propKey] = null;\n    } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {\n      node.__html = null;\n    } else {\n      node.attributes[propKey] = null;\n    }\n  },\n\n  setAttribute(node, propKey, propValue) {\n    if (propKey === 'className') {\n      propKey = 'class';\n    }\n\n    if (propKey == ID) {\n      this.nodeMaps[propValue] = node;\n    }\n\n    if (node.tagName === 'INPUT' &&\n      ( propKey == 'checked' && (node.attributes.type === 'checkbox' || node.attributes.type === 'radio')\n      || propKey == 'value')) {\n      node.attributes[propKey] = propValue;\n    } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {\n      node.__html = propValue.__html;\n    } else if (propValue != null) {\n      node.attributes[propKey] = propValue;\n    }\n  },\n\n  setStyle(node, style) {\n    for (let key in style) {\n      node.style[key] = style[key];\n    }\n  },\n\n  setNativeProps(node, props, shouldIgnoreStyleProp) {\n    for (let prop in props) {\n      let value = props[prop];\n      if (prop === CHILDREN) {\n        continue;\n      }\n\n      if (value != null) {\n        if (prop === STYLE) {\n          if (shouldIgnoreStyleProp) {\n            continue;\n          }\n          this.setStyle(node, value);\n        } else if (EVENT_PREFIX_REGEXP.test(prop)) {\n          let eventName = prop.slice(2).toLowerCase();\n          this.addEventListener(node, eventName, value);\n        } else {\n          this.setAttribute(node, prop, value);\n        }\n      }\n    }\n  }\n};\n\nexport default Driver;\n"
  },
  {
    "path": "packages/driver-universal/CHANGELOG.md",
    "content": "## Changelog\n\n## v3.5.0\n\n- Chore: use `import` instead of `require` in entry file\n\n## v3.4.0\n\n- Chore: remove kraken driver, using web instead.\n\n## v3.3.1\n\n- Chore: remove `Object.assign`\n- Chore: add @babel/helpers for project size\n- Fix: require weex module is `undefined`\n\n## v3.3.0\n\n- Chore: reduce size by exports fields\n\n### v3.2.0\n\n- Support bytedance/baidu/kuaishou miniapp\n\n### v3.1.7\n\n- Bump version\n\n### v3.1.6\n\n- Use `style-unit` convert `rpx`\n"
  },
  {
    "path": "packages/driver-universal/README.md",
    "content": "# driver-universal\n\n> Driver for Universal App.\n\nSupport both DOM(Web) and Weex, with normalized 750rpx support of screen width.\n## Install\n\n```bash\n$ npm install --save driver-universal\n```\n\n## Use\n\n```jsx\nimport { createElement, render } from 'rax';\nimport View from 'rax-view';\nimport Image from 'rax-image';\nimport DriverUniversal from 'driver-universal';\nfunction Example() {\n  return (\n    <View>\n      <Image width=\"560\" height=\"560\" src=\"https://img.alicdn.com/tps/TB1z.55OFXXXXcLXXXXXXXXXXXX-560-560.jpg\" />\n    </View>\n  );\n}\nrender(<Example />, null, {\n  driver: DriverUniversal\n});\n```\n\n## Driver `unit` difference\n| driver | length value without unit | 'rpx' unit |\n| ------ | ------------------------------ | --------------- |\n| driver-dom | Append 'px' unit| Translate to 'vw' |\n| driver-weex | Append weex 'px' unit | Translate to weex 'px' |\n| driver-universal | Append 'rpx' | Translate to 'vw' in web, and translate to 'px' in weex | \n"
  },
  {
    "path": "packages/driver-universal/package.json",
    "content": "{\n  \"name\": \"driver-universal\",\n  \"version\": \"3.5.0\",\n  \"description\": \"Driver for Universal App.\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"module\": \"es/index.js\",\n  \"exports\": {\n    \".\": {\n      \"web\": \"./es/web.js\",\n      \"weex\": \"./es/weex.js\",\n      \"miniapp\": \"./es/miniapp.js\",\n      \"wechat-miniprogram\": \"./es/miniapp.js\",\n      \"bytedance-microapp\": \"./es/miniapp.js\",\n      \"baidu-smartprogram\": \"./es/miniapp.js\",\n      \"kuaishou-miniprogram\": \"./es/miniapp.js\",\n      \"default\": \"./es/index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"sideEffects\": false,\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"devDependencies\": {\n    \"rax\": \"^1.0.0\"\n  },\n  \"dependencies\": {\n    \"driver-dom\": \"^2.0.5\",\n    \"driver-miniapp\": \"^0.1.0\",\n    \"driver-weex\": \"^2.0.0\",\n    \"universal-env\": \"^3.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/driver-universal/src/__tests__/css-custom-properties.js",
    "content": "import { createElement, render } from 'rax';\nimport DriverDOM from '../';\n\ndescribe('Support CSS custom properties', () => {\n  let container;\n  let logs;\n  const setProperty = CSSStyleDeclaration.prototype.setProperty;\n\n  beforeAll(() => {\n    CSSStyleDeclaration.prototype.setProperty = (prop, value) => {\n      logs.push([prop, value]);\n    };\n  });\n\n  afterAll(() => {\n    CSSStyleDeclaration.prototype.setProperty = setProperty;\n  });\n\n  beforeEach(() => {\n    container = document.createElement('div');\n    (document.body || document.documentElement).appendChild(container);\n    logs = [];\n  });\n\n  it('CSS custom properties works.', () => {\n    render((\n      <div style={{\n        '--backgroundColor': 'red',\n        backgroundColor: 'var(--backgroundColor)',\n      }}>\n        Test CSS custom properties.\n      </div>\n    ), container, {\n      driver: DriverDOM\n    });\n\n    expect(logs).toEqual([['--backgroundColor', 'red']]);\n  });\n});"
  },
  {
    "path": "packages/driver-universal/src/__tests__/dom-rpx-transformer.js",
    "content": "import { createElement, render } from 'rax';\nimport Driver from '../web';\n\ndescribe('Transform rpx', () => {\n  const CLIENT_WIDTH = 750;\n\n  it('CSS custom properties works.', () => {\n    global.DEVICE_WIDTH = CLIENT_WIDTH;\n\n    const container = document.createElement('div');\n    render((\n      <div style={{\n        margin: '75rpx 100vh'\n      }} />\n    ), container, {\n      driver: Driver,\n    });\n\n    expect(container.childNodes[0].style.margin).toEqual('10vw 100vh');\n  });\n\n  it('should automatically append `rpx` to relevant styles', () => {\n    const container = document.createElement('div');\n    render((\n      <div style={{\n        margin: 75\n      }} />\n    ), container, {\n      driver: Driver,\n    });\n\n    expect(container.childNodes[0].style.margin).toEqual('10vw');\n  });\n});\n"
  },
  {
    "path": "packages/driver-universal/src/index.d.ts",
    "content": "// Driver spec: https://github.com/alibaba/rax/blob/master/docs/en-US/driver-spec.md\ndeclare namespace Driver {\n  function createBody(): void;\n  function createEmpty(component: any): void;\n  function createText(): void;\n  function updateText(node: any, text: any)\n  function createElement(type: any, props: any, component: any)\n  function appendChild(node: any, parent: any)\n  function removeChild(node: any, parent: any)\n  function replaceChild(newChild: any, oldChild: any, parent: any)\n  function insertAfter(node: any, after: any, parent: any)\n  function insertBefore(node: any, before: any, parent: any)\n  function addEventListener(node: any, eventName: any, eventHandler: any)\n  function removeEventListener(node: any, eventName: any, eventHandler: any)\n  function setAttribute(node: any, propKey: any, propValue: any)\n  function removeAttribute(node: any, propKey: any)\n  function setStyle(node: any, styleObject: any)\n}\n\nexport default Driver;\n"
  },
  {
    "path": "packages/driver-universal/src/index.js",
    "content": "import {\n  isWeex,\n  isWeb,\n  isMiniApp,\n  isWeChatMiniProgram,\n  isByteDanceMicroApp,\n  isBaiduSmartProgram,\n  isKuaiShouMiniProgram\n} from 'universal-env';\n\nimport driverWeex from './weex';\nimport driverWeb from './web';\nimport driverMiniApp from './miniapp';\n\nlet currentDriver;\nif (isWeex) {\n  currentDriver = driverWeex;\n} else if (isWeb) {\n  currentDriver = driverWeb;\n} else if (isMiniApp || isWeChatMiniProgram || isByteDanceMicroApp || isBaiduSmartProgram || isKuaiShouMiniProgram) {\n  currentDriver = driverMiniApp;\n}\n\nexport default currentDriver;\n"
  },
  {
    "path": "packages/driver-universal/src/miniapp.js",
    "content": "import MiniAppDriver from 'driver-miniapp';\n\nexport default MiniAppDriver;\n"
  },
  {
    "path": "packages/driver-universal/src/web.js",
    "content": "import * as DriverDOM from 'driver-dom';\n\nexport default {\n  ...DriverDOM,\n  createElement(type, props, component) {\n    return DriverDOM.createElement(type, props, component, true);\n  },\n  setStyle(node, style) {\n    return DriverDOM.setStyle(node, style, true);\n  }\n};\n"
  },
  {
    "path": "packages/driver-universal/src/weex.js",
    "content": "import * as WeexDriver from 'driver-weex';\n\nexport default WeexDriver;\n"
  },
  {
    "path": "packages/driver-webgl/README.md",
    "content": "# driver-webgl\n\n> WebGL driver for Rax.\n\nComponents and APIs are based on `three.js` design and implementation. Use markup language and declarative writing to simplify development.\n\n## Install\ns\n```bash\n$ npm install --save driver-webgl\n```\n\n## Usage\n\n```jsx\nimport {createElement, Component, render} from 'rax';\nimport WebGLDriver from 'driver-webgl';\n\nclass HelloWorld extends Component {\n  constructor(props, context) {\n    super(props, context);\n    this.state = {\n      cubeRotation: [0, 0, 0]\n    };\n    this.width = window.innerWidth;\n    this.height = window.innerHeight;\n    this.cameraPosition = [0, 0, 5];\n  }\n\n  onFrame = () => {\n    this.setState({\n      cubeRotation: [\n        this.state.cubeRotation[0] + 0.01,\n        this.state.cubeRotation[1] + 0.01,\n        0\n      ]\n    });\n  }\n\n  render() {\n    return (\n      <scene\n        width={this.width}\n        height={this.height}\n        onFrame={this.onFrame}\n      >\n        <perspective-camera\n          fov={75}\n          aspect={this.width / this.height}\n          near={0.1}\n          far={1000}\n          position={this.cameraPosition}\n        />\n        <mesh\n          rotation={this.state.cubeRotation}\n        >\n          <box-geometry\n            width={1}\n            height={1}\n            depth={1}\n          />\n          <mesh-basic-material\n            color={0x00ff00}\n          />\n        </mesh>\n      </scene>\n    );\n  }\n}\n\nrender(<HelloWorld />, document.body, {\n  driver: WebGLDriver\n});\n```\n\n## Built-in Tags\n\n### Scenes\n* scene\n\n### Cameras\n* perspective-camera\n\n### Controls\n* orbit-controls\n* trackball-controls\n\n### Core\n* geometry\n* buffer-geometry\n* object-3d\n* raycaster\n\n### Geometries\n* box-geometry\n* cylinder-geometry\n* sphere-geometry\n\n### Lights\n* ambient-light\n* directional-light\n\n### Materials\n* line-basic-material\n* line-dashed-material\n* mesh-basic-material\n* mesh-lambert-material\n* mesh-phong-material\n* points-material\n\n### Objects\n* line\n* mesh\n* points\n"
  },
  {
    "path": "packages/driver-webgl/package.json",
    "content": "{\n  \"name\": \"driver-webgl\",\n  \"version\": \"1.0.0-beta.0\",\n  \"description\": \"WebGL driver for Rax.\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"keywords\": [\n    \"Rax\",\n    \"rax-component\",\n    \"react-component\",\n    \"webgl\",\n    \"three\"\n  ],\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"dependencies\": {\n    \"three\": \"^0.85.0\"\n  }\n}\n"
  },
  {
    "path": "packages/driver-webgl/src/components/cameras/PerspectiveCamera.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {fov, aspect, near, far} = props;\n    const PerspectiveCamera = new THREE.PerspectiveCamera(fov, aspect, near, far);\n    PerspectiveCamera.updateProperty = this.updateProperty;\n    return PerspectiveCamera;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  },\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/controls/OrbitControls.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {camera} = props;\n    const OrbitControls = new THREE.OrbitControls(camera);\n    OrbitControls.updateProperty = this.updateProperty;\n    return OrbitControls;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  },\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/controls/TrackballControls.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {camera} = props;\n    const TrackballControls = new THREE.TrackballControls(camera);\n    TrackballControls.updateProperty = this.updateProperty;\n    return TrackballControls;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  },\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/core/BufferGeometry.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const BufferGeometry = new THREE.BufferGeometry();\n    BufferGeometry.updateProperty = this.updateProperty;\n    Object.keys(props).forEach((key) => {\n      const item = props[key];\n      const {array, itemSize, normalized} = item;\n      const bufferAttribute = new THREE.BufferAttribute(array, itemSize, normalized);\n      BufferGeometry.addAttribute(key, bufferAttribute);\n    });\n    BufferGeometry.computeBoundingSphere();\n    return BufferGeometry;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  },\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/core/Geometry.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init() {\n    const Geometry = new THREE.Geometry();\n    Geometry.updateProperty = this.updateProperty;\n    return Geometry;\n  },\n  updateProperty(key, value) {\n    if (key === 'vertices') {\n      this.vertices = value.map((vertex) => new THREE.Vector3(vertex[0], vertex[1], vertex[2]));\n      return;\n    }\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  },\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/core/Object3D.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init() {\n    const Object3D = new THREE.Object3D();\n    Object3D.updateProperty = this.updateProperty;\n    return Object3D;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  },\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/core/Raycaster.js",
    "content": "import * as THREE from 'three';\n\nlet camera = null;\n\nexport default {\n  init(props) {\n    const {origin, direction, near, far} = props;\n    const Raycaster = new THREE.Raycaster(origin, direction, near, far);\n    Raycaster.updateProperty = this.updateProperty;\n    camera = props.camera;\n    return Raycaster;\n  },\n  updateProperty(key, value) {\n    if (key === 'camera') {\n      camera = value;\n    }\n    if (key === 'coords') {\n      this.setFromCamera(value, camera);\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/geometries/BoxGeometry.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {width, height, depth, widthSegments, heightSegments, depthSegments} = props;\n    const BoxGeometry = new THREE.BoxGeometry(\n      width,\n      height,\n      depth,\n      widthSegments,\n      heightSegments,\n      depthSegments\n    );\n    BoxGeometry.updateProperty = this.updateProperty;\n    return BoxGeometry;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/geometries/CylinderGeometry.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {\n      radiusTop,\n      radiusBottom,\n      height,\n      radialSegments,\n      heightSegments,\n      openEnded,\n      thetaStart,\n      thetaLength\n    } = props;\n    const CylinderGeometry = new THREE.CylinderGeometry(\n      radiusTop,\n      radiusBottom,\n      height,\n      radialSegments,\n      heightSegments,\n      openEnded,\n      thetaStart,\n      thetaLength\n    );\n    CylinderGeometry.updateProperty = this.updateProperty;\n    return CylinderGeometry;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/geometries/SphereGeometry.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength} = props;\n    const SphereGeometry = new THREE.SphereGeometry(\n      radius,\n      widthSegments,\n      heightSegments,\n      phiStart,\n      phiLength,\n      thetaStart,\n      thetaLength\n    );\n    SphereGeometry.updateProperty = this.updateProperty;\n    return SphereGeometry;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/index.js",
    "content": "import PerspectiveCamera from './cameras/PerspectiveCamera';\n\nimport OrbitControls from './controls/OrbitControls';\nimport TrackballControls from './controls/TrackballControls';\n\nimport BufferGeometry from './core/BufferGeometry';\nimport Geometry from './core/Geometry';\nimport Object3D from './core/Object3D';\nimport Raycaster from './core/Raycaster';\n\nimport BoxGeometry from './geometries/BoxGeometry';\nimport CylinderGeometry from './geometries/CylinderGeometry';\nimport SphereGeometry from './geometries/SphereGeometry';\n\nimport AmbientLight from './lights/AmbientLight';\nimport DirectionalLight from './lights/DirectionalLight';\n\nimport LineBasicMaterial from './materials/LineBasicMaterial';\nimport LineDashedMaterial from './materials/LineDashedMaterial';\nimport MeshBasicMaterial from './materials/MeshBasicMaterial';\nimport MeshLambertMaterial from './materials/MeshLambertMaterial';\nimport MeshPhongMaterial from './materials/MeshPhongMaterial';\nimport PointsMaterial from './materials/PointsMaterial';\n\nimport Line from './objects/Line';\nimport Mesh from './objects/Mesh';\nimport Points from './objects/Points';\n\nimport Scene from './scenes/Scene';\n\nexport default {\n  'perspective-camera': PerspectiveCamera,\n  'orbit-controls': OrbitControls,\n  'trackball-controls': TrackballControls,\n  'buffer-geometry': BufferGeometry,\n  'geometry': Geometry,\n  'object-3d': Object3D,\n  'raycaster': Raycaster,\n  'box-geometry': BoxGeometry,\n  'cylinder-geometry': CylinderGeometry,\n  'sphere-geometry': SphereGeometry,\n  'ambient-light': AmbientLight,\n  'directional-light': DirectionalLight,\n  'line-basic-material': LineBasicMaterial,\n  'line-dashed-material': LineDashedMaterial,\n  'mesh-basic-material': MeshBasicMaterial,\n  'mesh-lambert-material': MeshLambertMaterial,\n  'mesh-phong-material': MeshPhongMaterial,\n  'points-material': PointsMaterial,\n  'line': Line,\n  'mesh': Mesh,\n  'points': Points,\n  'scene': Scene\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/lights/AmbientLight.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {color, intensity} = props;\n    const AmbientLight = new THREE.AmbientLight(color, intensity);\n    AmbientLight.updateProperty = this.updateProperty;\n    return AmbientLight;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  },\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/lights/DirectionalLight.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {color, intensity} = props;\n    const DirectionalLight = new THREE.DirectionalLight(color, intensity);\n    DirectionalLight.updateProperty = this.updateProperty;\n    return DirectionalLight;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/materials/LineBasicMaterial.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const LineBasicMaterial = new THREE.LineBasicMaterial(props);\n    LineBasicMaterial.updateProperty = this.updateProperty;\n    return LineBasicMaterial;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/materials/LineDashedMaterial.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const LineDashedMateria = new THREE.LineDashedMateria(props);\n    LineDashedMateria.updateProperty = this.updateProperty;\n    return LineDashedMateria;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/materials/MeshBasicMaterial.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const MeshBasicMaterial = new THREE.MeshBasicMaterial(props);\n    MeshBasicMaterial.updateProperty = this.updateProperty;\n    return MeshBasicMaterial;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/materials/MeshLambertMaterial.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const MeshLambertMaterial = new THREE.MeshLambertMaterial(props);\n    MeshLambertMaterial.updateProperty = this.updateProperty;\n    return MeshLambertMaterial;\n  },\n  updateProperty(key, value) {\n    if (key === 'map') {\n      const map = new THREE.TextureLoader().load(value.src);\n      this.map = map;\n      return;\n    }\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/materials/MeshPhongMaterial.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const MeshPhongMaterial = new THREE.MeshPhongMaterial(props);\n    MeshPhongMaterial.updateProperty = this.updateProperty;\n    return MeshPhongMaterial;\n  },\n  updateProperty(key, value) {\n    if (key === 'map') {\n      const map = new THREE.TextureLoader().load(value.src);\n      this.map = map;\n      return;\n    }\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/materials/PointsMaterial.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const PointsMaterial = new THREE.PointsMaterial(props);\n    PointsMaterial.updateProperty = this.updateProperty;\n    return PointsMaterial;\n  },\n  updateProperty(key, value) {\n    if (key === 'map') {\n      const map = new THREE.TextureLoader().load(value.src);\n      this.map = map;\n      return;\n    }\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/objects/Line.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {geometry, material} = props;\n    const Line = new THREE.Line(geometry, material);\n    Line.updateProperty = this.updateProperty;\n    return Line;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/objects/Mesh.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {geometry, material} = props;\n    const Mesh = new THREE.Mesh(geometry, material);\n    Mesh.updateProperty = this.updateProperty;\n    return Mesh;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/objects/Points.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {geometry, material} = props;\n    const Point = new THREE.Points(geometry, material);\n    Point.updateProperty = this.updateProperty;\n    return Point;\n  },\n  updateProperty(key, value) {\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/components/scenes/Scene.js",
    "content": "import * as THREE from 'three';\n\nexport default {\n  init(props) {\n    const {\n      background = null,\n      fog = null,\n      overrideMaterial = null,\n      autoUpdate = true,\n      onFrame = () => {}\n    } = props;\n\n    const Scene = new THREE.Scene();\n    if (fog !== null) {\n      if (Object.hasOwnProperty.call(fog, 'density')) {\n        Scene.fog = new THREE.FogExp2(fog.color, fog.density);\n      } else {\n        Scene.fog = new THREE.Fog(fog.color, fog.near, fog.far);\n      }\n    }\n    Scene.background = background;\n    Scene.overrideMaterial = overrideMaterial;\n    Scene.autoUpdate = autoUpdate;\n    Scene.onFrame = onFrame;\n    Scene.updateProperty = this.updateProperty;\n    return Scene;\n  },\n  updateProperty(key, value) {\n    if (key === 'fog') {\n      if (Object.hasOwnProperty.call(value, 'density')) {\n        this.fog = new THREE.FogExp2(value.color, value.density);\n      } else {\n        this.fog = new THREE.Fog(value.color, value.near, value.far);\n      }\n      return;\n    }\n    if (Object.hasOwnProperty.call(this, key)) {\n      if (this[key] && this[key].set) {\n        return this[key].set.apply(this[key], Object.values(value));\n      }\n      this[key] = value;\n      return;\n    }\n  }\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/driver.js",
    "content": "import * as THREE from 'three';\nimport ThreeComponent from './components';\n\nconst CHILDREN = 'children';\nconst EVENT_PREFIX_REGEXP = /^on[A-Z]/;\nconst ID = 'uuid';\nconst nodeMaps = {};\n\nlet renderer = null;\nlet scene = null;\nlet camera = null;\n\nfunction createElement(type, props) {\n  return ThreeComponent[type].init(props);\n}\n\nconst Driver = {\n  getElementById(id) {\n    return nodeMaps[id];\n  },\n\n  createBody() {\n    if (document.getElementsByTagName('canvas').length !== 0) {\n      return document.getElementsByName('canvas').shift();\n    }\n\n    renderer = new THREE.WebGLRenderer();\n    renderer.setPixelRatio(window.devicePixelRatio);\n    renderer.setSize(window.innerWidth, window.innerHeight);\n    document.body.appendChild(renderer.domElement);\n    return renderer;\n  },\n\n  createEmpty() {\n    return createElement({\n      type: 'object-3d'\n    });\n  },\n\n  createElement(type, props) {\n    let node = createElement(type, props);\n    this.setNativeProps(node, props);\n    return node;\n  },\n\n  appendChild(node, parent) {\n    if (node.type === 'Scene') {\n      node.renderer = renderer;\n      scene = node;\n      return;\n    }\n    if (node.isCamera) {\n      camera = node;\n      return;\n    }\n    if (parent.type === 'Scene' && node.isObject3D) {\n      parent.add(node);\n    } else {\n      if (parent.isObject3D) {\n        if (node.isGeometry || node.isBufferGeometry) parent.geometry = node;\n        if (node.isMaterial) parent.material = node;\n      }\n    }\n    return renderer.render(scene, camera);\n  },\n\n  removeChild(node, parent) {\n    parent = parent || node.parent;\n    let id = node[ID];\n    if (id != null) {\n      nodeMaps[id] = null;\n    }\n    return parent.remove(node);\n  },\n\n  replaceChild(newChild, oldChild, parent) {\n    parent = parent || oldChild.parent;\n    this.removeChild(oldChild, parent);\n    this.appendChild(newChild, parent);\n  },\n\n  addEventListener(node, eventName, eventHandler) {\n    if (node.type === 'Scene') {\n      return document.body.addEventListener(eventName, eventHandler);\n    }\n    return node;\n  },\n\n  removeEventListener(node, eventName, eventHandler) {\n    if (node.type === 'Scene') {\n      return document.body.removeEventListener(eventName, eventHandler);\n    }\n    return node;\n  },\n\n  removeAttribute(node, propKey, propValue) {\n    // Noop\n  },\n\n  setAttribute(node, propKey, propValue) {\n    if (propKey == ID) {\n      nodeMaps[propValue] = node;\n    }\n    node.updateProperty(propKey, propValue);\n    return node;\n  },\n\n  afterRender() {\n    render();\n  },\n\n  setNativeProps(node, props) {\n    for (let prop in props) {\n      let value = props[prop];\n      if (prop === CHILDREN) {\n        continue;\n      }\n      if (value != null) {\n        if (EVENT_PREFIX_REGEXP.test(prop)) {\n          let eventName = prop.slice(2).toLowerCase();\n          this.addEventListener(node, eventName, value);\n        } else {\n          this.setAttribute(node, prop, value);\n        }\n      }\n    }\n  }\n};\n\nconst render = () => {\n  window.requestAnimationFrame(render);\n  renderer.render(scene, camera);\n  scene.onFrame();\n};\n\nexport default Driver;\n"
  },
  {
    "path": "packages/driver-webgl/src/index.js",
    "content": "import * as THREE from 'three';\n\nimport TrackballControls from './plugin/controls/TrackballControls';\nimport OrbitControls from './plugin/controls/OrbitControls';\n\nimport Driver from './driver';\n\nexport default Driver;\nexport {\n  THREE\n};\n"
  },
  {
    "path": "packages/driver-webgl/src/plugin/controls/OrbitControls.js",
    "content": "import * as THREE from 'three';\n\n/**\n * @author qiao / https://github.com/qiao\n * @author mrdoob / http://mrdoob.com\n * @author alteredq / http://alteredqualia.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author erich666 / http://erichaines.com\n */\n\n// This set of controls performs orbiting, dollying (zooming), and panning.\n// Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n//\n//    Orbit - left mouse / touch: one finger move\n//    Zoom - middle mouse, or mousewheel / touch: two finger spread or squish\n//    Pan - right mouse, or arrow keys / touch: three finger swipe\n\nTHREE.OrbitControls = function( object, domElement ) {\n  this.object = object;\n\n  this.domElement = domElement !== undefined ? domElement : document;\n\n  // Set to false to disable this control\n  this.enabled = true;\n\n  // \"target\" sets the location of focus, where the object orbits around\n  this.target = new THREE.Vector3();\n\n  // How far you can dolly in and out ( PerspectiveCamera only )\n  this.minDistance = 0;\n  this.maxDistance = Infinity;\n\n  // How far you can zoom in and out ( OrthographicCamera only )\n  this.minZoom = 0;\n  this.maxZoom = Infinity;\n\n  // How far you can orbit vertically, upper and lower limits.\n  // Range is 0 to Math.PI radians.\n  this.minPolarAngle = 0; // radians\n  this.maxPolarAngle = Math.PI; // radians\n\n  // How far you can orbit horizontally, upper and lower limits.\n  // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].\n  this.minAzimuthAngle = - Infinity; // radians\n  this.maxAzimuthAngle = Infinity; // radians\n\n  // Set to true to enable damping (inertia)\n  // If damping is enabled, you must call controls.update() in your animation loop\n  this.enableDamping = false;\n  this.dampingFactor = 0.25;\n\n  // This option actually enables dollying in and out; left as \"zoom\" for backwards compatibility.\n  // Set to false to disable zooming\n  this.enableZoom = true;\n  this.zoomSpeed = 1.0;\n\n  // Set to false to disable rotating\n  this.enableRotate = true;\n  this.rotateSpeed = 1.0;\n\n  // Set to false to disable panning\n  this.enablePan = true;\n  this.keyPanSpeed = 7.0; // pixels moved per arrow key push\n\n  // Set to true to automatically rotate around the target\n  // If auto-rotate is enabled, you must call controls.update() in your animation loop\n  this.autoRotate = false;\n  this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\n\n  // Set to false to disable use of the keys\n  this.enableKeys = true;\n\n  // The four arrow keys\n  this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };\n\n  // Mouse buttons\n  this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };\n\n  // for reset\n  this.target0 = this.target.clone();\n  this.position0 = this.object.position.clone();\n  this.zoom0 = this.object.zoom;\n\n  //\n  // public methods\n  //\n\n  this.getPolarAngle = function() {\n    return spherical.phi;\n  };\n\n  this.getAzimuthalAngle = function() {\n    return spherical.theta;\n  };\n\n  this.saveState = function() {\n    scope.target0.copy( scope.target );\n    scope.position0.copy( scope.object.position );\n    scope.zoom0 = scope.object.zoom;\n  };\n\n  this.reset = function() {\n    scope.target.copy( scope.target0 );\n    scope.object.position.copy( scope.position0 );\n    scope.object.zoom = scope.zoom0;\n\n    scope.object.updateProjectionMatrix();\n    scope.dispatchEvent( changeEvent );\n\n    scope.update();\n\n    state = STATE.NONE;\n  };\n\n  // this method is exposed, but perhaps it would be better if we can make it private...\n  this.update = function() {\n    var offset = new THREE.Vector3();\n\n    // so camera.up is the orbit axis\n    var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );\n    var quatInverse = quat.clone().inverse();\n\n    var lastPosition = new THREE.Vector3();\n    var lastQuaternion = new THREE.Quaternion();\n\n    return function update() {\n      var position = scope.object.position;\n\n      offset.copy( position ).sub( scope.target );\n\n      // rotate offset to \"y-axis-is-up\" space\n      offset.applyQuaternion( quat );\n\n      // angle from z-axis around y-axis\n      spherical.setFromVector3( offset );\n\n      if ( scope.autoRotate && state === STATE.NONE ) {\n        rotateLeft( getAutoRotationAngle() );\n      }\n\n      spherical.theta += sphericalDelta.theta;\n      spherical.phi += sphericalDelta.phi;\n\n      // restrict theta to be between desired limits\n      spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) );\n\n      // restrict phi to be between desired limits\n      spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );\n\n      spherical.makeSafe();\n\n\n      spherical.radius *= scale;\n\n      // restrict radius to be between desired limits\n      spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );\n\n      // move target to panned location\n      scope.target.add( panOffset );\n\n      offset.setFromSpherical( spherical );\n\n      // rotate offset back to \"camera-up-vector-is-up\" space\n      offset.applyQuaternion( quatInverse );\n\n      position.copy( scope.target ).add( offset );\n\n      scope.object.lookAt( scope.target );\n\n      if ( scope.enableDamping === true ) {\n        sphericalDelta.theta *= 1 - scope.dampingFactor;\n        sphericalDelta.phi *= 1 - scope.dampingFactor;\n      } else {\n        sphericalDelta.set( 0, 0, 0 );\n      }\n\n      scale = 1;\n      panOffset.set( 0, 0, 0 );\n\n      // update condition is:\n      // min(camera displacement, camera rotation in radians)^2 > EPS\n      // using small-angle approximation cos(x/2) = 1 - x^2 / 8\n\n      if ( zoomChanged ||\n        lastPosition.distanceToSquared( scope.object.position ) > EPS ||\n        8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {\n        scope.dispatchEvent( changeEvent );\n\n        lastPosition.copy( scope.object.position );\n        lastQuaternion.copy( scope.object.quaternion );\n        zoomChanged = false;\n\n        return true;\n      }\n\n      return false;\n    };\n  }();\n\n  this.dispose = function() {\n    scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false );\n    scope.domElement.removeEventListener( 'mousedown', onMouseDown, false );\n    scope.domElement.removeEventListener( 'wheel', onMouseWheel, false );\n\n    scope.domElement.removeEventListener( 'touchstart', onTouchStart, false );\n    scope.domElement.removeEventListener( 'touchend', onTouchEnd, false );\n    scope.domElement.removeEventListener( 'touchmove', onTouchMove, false );\n\n    document.removeEventListener( 'mousemove', onMouseMove, false );\n    document.removeEventListener( 'mouseup', onMouseUp, false );\n\n    window.removeEventListener( 'keydown', onKeyDown, false );\n\n    // scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?\n  };\n\n  //\n  // internals\n  //\n\n  var scope = this;\n\n  var changeEvent = { type: 'change' };\n  var startEvent = { type: 'start' };\n  var endEvent = { type: 'end' };\n\n  var STATE = { NONE: - 1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 };\n\n  var state = STATE.NONE;\n\n  var EPS = 0.000001;\n\n  // current position in spherical coordinates\n  var spherical = new THREE.Spherical();\n  var sphericalDelta = new THREE.Spherical();\n\n  var scale = 1;\n  var panOffset = new THREE.Vector3();\n  var zoomChanged = false;\n\n  var rotateStart = new THREE.Vector2();\n  var rotateEnd = new THREE.Vector2();\n  var rotateDelta = new THREE.Vector2();\n\n  var panStart = new THREE.Vector2();\n  var panEnd = new THREE.Vector2();\n  var panDelta = new THREE.Vector2();\n\n  var dollyStart = new THREE.Vector2();\n  var dollyEnd = new THREE.Vector2();\n  var dollyDelta = new THREE.Vector2();\n\n  function getAutoRotationAngle() {\n    return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\n  }\n\n  function getZoomScale() {\n    return Math.pow( 0.95, scope.zoomSpeed );\n  }\n\n  function rotateLeft( angle ) {\n    sphericalDelta.theta -= angle;\n  }\n\n  function rotateUp( angle ) {\n    sphericalDelta.phi -= angle;\n  }\n\n  var panLeft = function() {\n    var v = new THREE.Vector3();\n\n    return function panLeft( distance, objectMatrix ) {\n      v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix\n      v.multiplyScalar( - distance );\n\n      panOffset.add( v );\n    };\n  }();\n\n  var panUp = function() {\n    var v = new THREE.Vector3();\n\n    return function panUp( distance, objectMatrix ) {\n      v.setFromMatrixColumn( objectMatrix, 1 ); // get Y column of objectMatrix\n      v.multiplyScalar( distance );\n\n      panOffset.add( v );\n    };\n  }();\n\n  // deltaX and deltaY are in pixels; right and down are positive\n  var pan = function() {\n    var offset = new THREE.Vector3();\n\n    return function pan( deltaX, deltaY ) {\n      var element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\n      if ( scope.object instanceof THREE.PerspectiveCamera ) {\n        // perspective\n        var position = scope.object.position;\n        offset.copy( position ).sub( scope.target );\n        var targetDistance = offset.length();\n\n        // half of the fov is center to top of screen\n        targetDistance *= Math.tan( scope.object.fov / 2 * Math.PI / 180.0 );\n\n        // we actually don't use screenWidth, since perspective camera is fixed to screen height\n        panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );\n        panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );\n      } else if ( scope.object instanceof THREE.OrthographicCamera ) {\n        // orthographic\n        panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );\n        panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );\n      } else {\n        // camera neither orthographic nor perspective\n        console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\n        scope.enablePan = false;\n      }\n    };\n  }();\n\n  function dollyIn( dollyScale ) {\n    if ( scope.object instanceof THREE.PerspectiveCamera ) {\n      scale /= dollyScale;\n    } else if ( scope.object instanceof THREE.OrthographicCamera ) {\n      scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );\n      scope.object.updateProjectionMatrix();\n      zoomChanged = true;\n    } else {\n      console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n      scope.enableZoom = false;\n    }\n  }\n\n  function dollyOut( dollyScale ) {\n    if ( scope.object instanceof THREE.PerspectiveCamera ) {\n      scale *= dollyScale;\n    } else if ( scope.object instanceof THREE.OrthographicCamera ) {\n      scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );\n      scope.object.updateProjectionMatrix();\n      zoomChanged = true;\n    } else {\n      console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n      scope.enableZoom = false;\n    }\n  }\n\n  //\n  // event callbacks - update the object state\n  //\n\n  function handleMouseDownRotate( event ) {\n    // console.log( 'handleMouseDownRotate' );\n\n    rotateStart.set( event.clientX, event.clientY );\n  }\n\n  function handleMouseDownDolly( event ) {\n    // console.log( 'handleMouseDownDolly' );\n\n    dollyStart.set( event.clientX, event.clientY );\n  }\n\n  function handleMouseDownPan( event ) {\n    // console.log( 'handleMouseDownPan' );\n\n    panStart.set( event.clientX, event.clientY );\n  }\n\n  function handleMouseMoveRotate( event ) {\n    // console.log( 'handleMouseMoveRotate' );\n\n    rotateEnd.set( event.clientX, event.clientY );\n    rotateDelta.subVectors( rotateEnd, rotateStart );\n\n    var element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\n    // rotating across whole screen goes 360 degrees around\n    rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );\n\n    // rotating up and down along whole screen attempts to go 360, but limited to 180\n    rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );\n\n    rotateStart.copy( rotateEnd );\n\n    scope.update();\n  }\n\n  function handleMouseMoveDolly( event ) {\n    // console.log( 'handleMouseMoveDolly' );\n\n    dollyEnd.set( event.clientX, event.clientY );\n\n    dollyDelta.subVectors( dollyEnd, dollyStart );\n\n    if ( dollyDelta.y > 0 ) {\n      dollyIn( getZoomScale() );\n    } else if ( dollyDelta.y < 0 ) {\n      dollyOut( getZoomScale() );\n    }\n\n    dollyStart.copy( dollyEnd );\n\n    scope.update();\n  }\n\n  function handleMouseMovePan( event ) {\n    // console.log( 'handleMouseMovePan' );\n\n    panEnd.set( event.clientX, event.clientY );\n\n    panDelta.subVectors( panEnd, panStart );\n\n    pan( panDelta.x, panDelta.y );\n\n    panStart.copy( panEnd );\n\n    scope.update();\n  }\n\n  function handleMouseUp( event ) {\n\n    // console.log( 'handleMouseUp' );\n\n  }\n\n  function handleMouseWheel( event ) {\n    // console.log( 'handleMouseWheel' );\n\n    if ( event.deltaY < 0 ) {\n      dollyOut( getZoomScale() );\n    } else if ( event.deltaY > 0 ) {\n      dollyIn( getZoomScale() );\n    }\n\n    scope.update();\n  }\n\n  function handleKeyDown( event ) {\n    // console.log( 'handleKeyDown' );\n\n    switch ( event.keyCode ) {\n      case scope.keys.UP:\n        pan( 0, scope.keyPanSpeed );\n        scope.update();\n        break;\n\n      case scope.keys.BOTTOM:\n        pan( 0, - scope.keyPanSpeed );\n        scope.update();\n        break;\n\n      case scope.keys.LEFT:\n        pan( scope.keyPanSpeed, 0 );\n        scope.update();\n        break;\n\n      case scope.keys.RIGHT:\n        pan( - scope.keyPanSpeed, 0 );\n        scope.update();\n        break;\n    }\n  }\n\n  function handleTouchStartRotate( event ) {\n    // console.log( 'handleTouchStartRotate' );\n\n    rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n  }\n\n  function handleTouchStartDolly( event ) {\n    // console.log( 'handleTouchStartDolly' );\n\n    var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n    var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\n    var distance = Math.sqrt( dx * dx + dy * dy );\n\n    dollyStart.set( 0, distance );\n  }\n\n  function handleTouchStartPan( event ) {\n    // console.log( 'handleTouchStartPan' );\n\n    panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n  }\n\n  function handleTouchMoveRotate( event ) {\n    // console.log( 'handleTouchMoveRotate' );\n\n    rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n    rotateDelta.subVectors( rotateEnd, rotateStart );\n\n    var element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\n    // rotating across whole screen goes 360 degrees around\n    rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );\n\n    // rotating up and down along whole screen attempts to go 360, but limited to 180\n    rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );\n\n    rotateStart.copy( rotateEnd );\n\n    scope.update();\n  }\n\n  function handleTouchMoveDolly( event ) {\n    // console.log( 'handleTouchMoveDolly' );\n\n    var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n    var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\n    var distance = Math.sqrt( dx * dx + dy * dy );\n\n    dollyEnd.set( 0, distance );\n\n    dollyDelta.subVectors( dollyEnd, dollyStart );\n\n    if ( dollyDelta.y > 0 ) {\n      dollyOut( getZoomScale() );\n    } else if ( dollyDelta.y < 0 ) {\n      dollyIn( getZoomScale() );\n    }\n\n    dollyStart.copy( dollyEnd );\n\n    scope.update();\n  }\n\n  function handleTouchMovePan( event ) {\n    // console.log( 'handleTouchMovePan' );\n\n    panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\n    panDelta.subVectors( panEnd, panStart );\n\n    pan( panDelta.x, panDelta.y );\n\n    panStart.copy( panEnd );\n\n    scope.update();\n  }\n\n  function handleTouchEnd( event ) {\n\n    // console.log( 'handleTouchEnd' );\n\n  }\n\n  //\n  // event handlers - FSM: listen for events and reset state\n  //\n\n  function onMouseDown( event ) {\n    if ( scope.enabled === false ) return;\n\n    event.preventDefault();\n\n    switch ( event.button ) {\n      case scope.mouseButtons.ORBIT:\n\n        if ( scope.enableRotate === false ) return;\n\n        handleMouseDownRotate( event );\n\n        state = STATE.ROTATE;\n\n        break;\n\n      case scope.mouseButtons.ZOOM:\n\n        if ( scope.enableZoom === false ) return;\n\n        handleMouseDownDolly( event );\n\n        state = STATE.DOLLY;\n\n        break;\n\n      case scope.mouseButtons.PAN:\n\n        if ( scope.enablePan === false ) return;\n\n        handleMouseDownPan( event );\n\n        state = STATE.PAN;\n\n        break;\n    }\n\n    if ( state !== STATE.NONE ) {\n      document.addEventListener( 'mousemove', onMouseMove, false );\n      document.addEventListener( 'mouseup', onMouseUp, false );\n\n      scope.dispatchEvent( startEvent );\n    }\n  }\n\n  function onMouseMove( event ) {\n    if ( scope.enabled === false ) return;\n\n    event.preventDefault();\n\n    switch ( state ) {\n      case STATE.ROTATE:\n\n        if ( scope.enableRotate === false ) return;\n\n        handleMouseMoveRotate( event );\n\n        break;\n\n      case STATE.DOLLY:\n\n        if ( scope.enableZoom === false ) return;\n\n        handleMouseMoveDolly( event );\n\n        break;\n\n      case STATE.PAN:\n\n        if ( scope.enablePan === false ) return;\n\n        handleMouseMovePan( event );\n\n        break;\n    }\n  }\n\n  function onMouseUp( event ) {\n    if ( scope.enabled === false ) return;\n\n    handleMouseUp( event );\n\n    document.removeEventListener( 'mousemove', onMouseMove, false );\n    document.removeEventListener( 'mouseup', onMouseUp, false );\n\n    scope.dispatchEvent( endEvent );\n\n    state = STATE.NONE;\n  }\n\n  function onMouseWheel( event ) {\n    if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE && state !== STATE.ROTATE ) return;\n\n    event.preventDefault();\n    event.stopPropagation();\n\n    handleMouseWheel( event );\n\n    scope.dispatchEvent( startEvent ); // not sure why these are here...\n    scope.dispatchEvent( endEvent );\n  }\n\n  function onKeyDown( event ) {\n    if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return;\n\n    handleKeyDown( event );\n  }\n\n  function onTouchStart( event ) {\n    if ( scope.enabled === false ) return;\n\n    switch ( event.touches.length ) {\n      case 1: // one-fingered touch: rotate\n\n        if ( scope.enableRotate === false ) return;\n\n        handleTouchStartRotate( event );\n\n        state = STATE.TOUCH_ROTATE;\n\n        break;\n\n      case 2: // two-fingered touch: dolly\n\n        if ( scope.enableZoom === false ) return;\n\n        handleTouchStartDolly( event );\n\n        state = STATE.TOUCH_DOLLY;\n\n        break;\n\n      case 3: // three-fingered touch: pan\n\n        if ( scope.enablePan === false ) return;\n\n        handleTouchStartPan( event );\n\n        state = STATE.TOUCH_PAN;\n\n        break;\n\n      default:\n\n        state = STATE.NONE;\n    }\n\n    if ( state !== STATE.NONE ) {\n      scope.dispatchEvent( startEvent );\n    }\n  }\n\n  function onTouchMove( event ) {\n    if ( scope.enabled === false ) return;\n\n    event.preventDefault();\n    event.stopPropagation();\n\n    switch ( event.touches.length ) {\n      case 1: // one-fingered touch: rotate\n\n        if ( scope.enableRotate === false ) return;\n        if ( state !== STATE.TOUCH_ROTATE ) return; // is this needed?...\n\n        handleTouchMoveRotate( event );\n\n        break;\n\n      case 2: // two-fingered touch: dolly\n\n        if ( scope.enableZoom === false ) return;\n        if ( state !== STATE.TOUCH_DOLLY ) return; // is this needed?...\n\n        handleTouchMoveDolly( event );\n\n        break;\n\n      case 3: // three-fingered touch: pan\n\n        if ( scope.enablePan === false ) return;\n        if ( state !== STATE.TOUCH_PAN ) return; // is this needed?...\n\n        handleTouchMovePan( event );\n\n        break;\n\n      default:\n\n        state = STATE.NONE;\n    }\n  }\n\n  function onTouchEnd( event ) {\n    if ( scope.enabled === false ) return;\n\n    handleTouchEnd( event );\n\n    scope.dispatchEvent( endEvent );\n\n    state = STATE.NONE;\n  }\n\n  function onContextMenu( event ) {\n    event.preventDefault();\n  }\n\n  //\n\n  scope.domElement.addEventListener( 'contextmenu', onContextMenu, false );\n\n  scope.domElement.addEventListener( 'mousedown', onMouseDown, false );\n  scope.domElement.addEventListener( 'wheel', onMouseWheel, false );\n\n  scope.domElement.addEventListener( 'touchstart', onTouchStart, false );\n  scope.domElement.addEventListener( 'touchend', onTouchEnd, false );\n  scope.domElement.addEventListener( 'touchmove', onTouchMove, false );\n\n  window.addEventListener( 'keydown', onKeyDown, false );\n\n  // force an update at start\n\n  this.update();\n};\n\nTHREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );\nTHREE.OrbitControls.prototype.constructor = THREE.OrbitControls;\n\nObject.defineProperties( THREE.OrbitControls.prototype, {\n\n  center: {\n\n    get: function() {\n      console.warn( 'THREE.OrbitControls: .center has been renamed to .target' );\n      return this.target;\n    }\n\n  },\n\n  // backward compatibility\n\n  noZoom: {\n\n    get: function() {\n      console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );\n      return ! this.enableZoom;\n    },\n\n    set: function( value ) {\n      console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );\n      this.enableZoom = ! value;\n    }\n\n  },\n\n  noRotate: {\n\n    get: function() {\n      console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );\n      return ! this.enableRotate;\n    },\n\n    set: function( value ) {\n      console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );\n      this.enableRotate = ! value;\n    }\n\n  },\n\n  noPan: {\n\n    get: function() {\n      console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );\n      return ! this.enablePan;\n    },\n\n    set: function( value ) {\n      console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );\n      this.enablePan = ! value;\n    }\n\n  },\n\n  noKeys: {\n\n    get: function() {\n      console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );\n      return ! this.enableKeys;\n    },\n\n    set: function( value ) {\n      console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );\n      this.enableKeys = ! value;\n    }\n\n  },\n\n  staticMoving: {\n\n    get: function() {\n      console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );\n      return ! this.enableDamping;\n    },\n\n    set: function( value ) {\n      console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );\n      this.enableDamping = ! value;\n    }\n\n  },\n\n  dynamicDampingFactor: {\n\n    get: function() {\n      console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );\n      return this.dampingFactor;\n    },\n\n    set: function( value ) {\n      console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );\n      this.dampingFactor = value;\n    }\n\n  }\n\n} );\n"
  },
  {
    "path": "packages/driver-webgl/src/plugin/controls/TrackballControls.js",
    "content": "import * as THREE from 'three';\n\n/**\n * @author Eberhard Graether / http://egraether.com/\n * @author Mark Lundin   / http://mark-lundin.com\n * @author Simone Manini / http://daron1337.github.io\n * @author Luca Antiga   / http://lantiga.github.io\n */\n\nTHREE.TrackballControls = function( object, domElement ) {\n  var _this = this;\n  var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };\n\n  this.object = object;\n  this.domElement = domElement !== undefined ? domElement : document;\n\n  // API\n\n  this.enabled = true;\n\n  this.screen = { left: 0, top: 0, width: 0, height: 0 };\n\n  this.rotateSpeed = 1.0;\n  this.zoomSpeed = 1.2;\n  this.panSpeed = 0.3;\n\n  this.noRotate = false;\n  this.noZoom = false;\n  this.noPan = false;\n\n  this.staticMoving = false;\n  this.dynamicDampingFactor = 0.2;\n\n  this.minDistance = 0;\n  this.maxDistance = Infinity;\n\n  this.keys = [ 65 /* A */, 83 /* S */, 68 /* D */ ];\n\n  // internals\n\n  this.target = new THREE.Vector3();\n\n  var EPS = 0.000001;\n\n  var lastPosition = new THREE.Vector3();\n\n  var _state = STATE.NONE,\n    _prevState = STATE.NONE,\n\n    _eye = new THREE.Vector3(),\n\n    _movePrev = new THREE.Vector2(),\n    _moveCurr = new THREE.Vector2(),\n\n    _lastAxis = new THREE.Vector3(),\n    _lastAngle = 0,\n\n    _zoomStart = new THREE.Vector2(),\n    _zoomEnd = new THREE.Vector2(),\n\n    _touchZoomDistanceStart = 0,\n    _touchZoomDistanceEnd = 0,\n\n    _panStart = new THREE.Vector2(),\n    _panEnd = new THREE.Vector2();\n\n  // for reset\n\n  this.target0 = this.target.clone();\n  this.position0 = this.object.position.clone();\n  this.up0 = this.object.up.clone();\n\n  // events\n\n  var changeEvent = { type: 'change' };\n  var startEvent = { type: 'start' };\n  var endEvent = { type: 'end' };\n\n\n  // methods\n\n  this.handleResize = function() {\n    if ( this.domElement === document ) {\n      this.screen.left = 0;\n      this.screen.top = 0;\n      this.screen.width = window.innerWidth;\n      this.screen.height = window.innerHeight;\n    } else {\n      var box = this.domElement.getBoundingClientRect();\n      // adjustments come from similar code in the jquery offset() function\n      var d = this.domElement.ownerDocument.documentElement;\n      this.screen.left = box.left + window.pageXOffset - d.clientLeft;\n      this.screen.top = box.top + window.pageYOffset - d.clientTop;\n      this.screen.width = box.width;\n      this.screen.height = box.height;\n    }\n  };\n\n  this.handleEvent = function( event ) {\n    if ( typeof this[ event.type ] == 'function' ) {\n      this[ event.type ]( event );\n    }\n  };\n\n  var getMouseOnScreen = ( function() {\n    var vector = new THREE.Vector2();\n\n    return function getMouseOnScreen( pageX, pageY ) {\n      vector.set(\n        ( pageX - _this.screen.left ) / _this.screen.width,\n        ( pageY - _this.screen.top ) / _this.screen.height\n      );\n\n      return vector;\n    };\n  }() );\n\n  var getMouseOnCircle = ( function() {\n    var vector = new THREE.Vector2();\n\n    return function getMouseOnCircle( pageX, pageY ) {\n      vector.set(\n        ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ),\n        ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width // screen.width intentional\n      );\n\n      return vector;\n    };\n  }() );\n\n  this.rotateCamera = ( function() {\n    var axis = new THREE.Vector3(),\n      quaternion = new THREE.Quaternion(),\n      eyeDirection = new THREE.Vector3(),\n      objectUpDirection = new THREE.Vector3(),\n      objectSidewaysDirection = new THREE.Vector3(),\n      moveDirection = new THREE.Vector3(),\n      angle;\n\n    return function rotateCamera() {\n      moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );\n      angle = moveDirection.length();\n\n      if ( angle ) {\n        _eye.copy( _this.object.position ).sub( _this.target );\n\n        eyeDirection.copy( _eye ).normalize();\n        objectUpDirection.copy( _this.object.up ).normalize();\n        objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();\n\n        objectUpDirection.setLength( _moveCurr.y - _movePrev.y );\n        objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );\n\n        moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );\n\n        axis.crossVectors( moveDirection, _eye ).normalize();\n\n        angle *= _this.rotateSpeed;\n        quaternion.setFromAxisAngle( axis, angle );\n\n        _eye.applyQuaternion( quaternion );\n        _this.object.up.applyQuaternion( quaternion );\n\n        _lastAxis.copy( axis );\n        _lastAngle = angle;\n      } else if ( ! _this.staticMoving && _lastAngle ) {\n        _lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor );\n        _eye.copy( _this.object.position ).sub( _this.target );\n        quaternion.setFromAxisAngle( _lastAxis, _lastAngle );\n        _eye.applyQuaternion( quaternion );\n        _this.object.up.applyQuaternion( quaternion );\n      }\n\n      _movePrev.copy( _moveCurr );\n    };\n  }() );\n\n\n  this.zoomCamera = function() {\n    var factor;\n\n    if ( _state === STATE.TOUCH_ZOOM_PAN ) {\n      factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;\n      _touchZoomDistanceStart = _touchZoomDistanceEnd;\n      _eye.multiplyScalar( factor );\n    } else {\n      factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;\n\n      if ( factor !== 1.0 && factor > 0.0 ) {\n        _eye.multiplyScalar( factor );\n      }\n\n      if ( _this.staticMoving ) {\n        _zoomStart.copy( _zoomEnd );\n      } else {\n        _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;\n      }\n    }\n  };\n\n  this.panCamera = ( function() {\n    var mouseChange = new THREE.Vector2(),\n      objectUp = new THREE.Vector3(),\n      pan = new THREE.Vector3();\n\n    return function panCamera() {\n      mouseChange.copy( _panEnd ).sub( _panStart );\n\n      if ( mouseChange.lengthSq() ) {\n        mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );\n\n        pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );\n        pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );\n\n        _this.object.position.add( pan );\n        _this.target.add( pan );\n\n        if ( _this.staticMoving ) {\n          _panStart.copy( _panEnd );\n        } else {\n          _panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );\n        }\n      }\n    };\n  }() );\n\n  this.checkDistances = function() {\n    if ( ! _this.noZoom || ! _this.noPan ) {\n      if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {\n        _this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) );\n        _zoomStart.copy( _zoomEnd );\n      }\n\n      if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {\n        _this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );\n        _zoomStart.copy( _zoomEnd );\n      }\n    }\n  };\n\n  this.update = function() {\n    _eye.subVectors( _this.object.position, _this.target );\n\n    if ( ! _this.noRotate ) {\n      _this.rotateCamera();\n    }\n\n    if ( ! _this.noZoom ) {\n      _this.zoomCamera();\n    }\n\n    if ( ! _this.noPan ) {\n      _this.panCamera();\n    }\n\n    _this.object.position.addVectors( _this.target, _eye );\n\n    _this.checkDistances();\n\n    _this.object.lookAt( _this.target );\n\n    if ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) {\n      _this.dispatchEvent( changeEvent );\n\n      lastPosition.copy( _this.object.position );\n    }\n  };\n\n  this.reset = function() {\n    _state = STATE.NONE;\n    _prevState = STATE.NONE;\n\n    _this.target.copy( _this.target0 );\n    _this.object.position.copy( _this.position0 );\n    _this.object.up.copy( _this.up0 );\n\n    _eye.subVectors( _this.object.position, _this.target );\n\n    _this.object.lookAt( _this.target );\n\n    _this.dispatchEvent( changeEvent );\n\n    lastPosition.copy( _this.object.position );\n  };\n\n  // listeners\n\n  function keydown( event ) {\n    if ( _this.enabled === false ) return;\n\n    window.removeEventListener( 'keydown', keydown );\n\n    _prevState = _state;\n\n    if ( _state !== STATE.NONE ) {\n      return;\n    } else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) {\n      _state = STATE.ROTATE;\n    } else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) {\n      _state = STATE.ZOOM;\n    } else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) {\n      _state = STATE.PAN;\n    }\n  }\n\n  function keyup( event ) {\n    if ( _this.enabled === false ) return;\n\n    _state = _prevState;\n\n    window.addEventListener( 'keydown', keydown, false );\n  }\n\n  function mousedown( event ) {\n    if ( _this.enabled === false ) return;\n\n    event.preventDefault();\n    event.stopPropagation();\n\n    if ( _state === STATE.NONE ) {\n      _state = event.button;\n    }\n\n    if ( _state === STATE.ROTATE && ! _this.noRotate ) {\n      _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );\n      _movePrev.copy( _moveCurr );\n    } else if ( _state === STATE.ZOOM && ! _this.noZoom ) {\n      _zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );\n      _zoomEnd.copy( _zoomStart );\n    } else if ( _state === STATE.PAN && ! _this.noPan ) {\n      _panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );\n      _panEnd.copy( _panStart );\n    }\n\n    document.addEventListener( 'mousemove', mousemove, false );\n    document.addEventListener( 'mouseup', mouseup, false );\n\n    _this.dispatchEvent( startEvent );\n  }\n\n  function mousemove( event ) {\n    if ( _this.enabled === false ) return;\n\n    event.preventDefault();\n    event.stopPropagation();\n\n    if ( _state === STATE.ROTATE && ! _this.noRotate ) {\n      _movePrev.copy( _moveCurr );\n      _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );\n    } else if ( _state === STATE.ZOOM && ! _this.noZoom ) {\n      _zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );\n    } else if ( _state === STATE.PAN && ! _this.noPan ) {\n      _panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );\n    }\n  }\n\n  function mouseup( event ) {\n    if ( _this.enabled === false ) return;\n\n    event.preventDefault();\n    event.stopPropagation();\n\n    _state = STATE.NONE;\n\n    document.removeEventListener( 'mousemove', mousemove );\n    document.removeEventListener( 'mouseup', mouseup );\n    _this.dispatchEvent( endEvent );\n  }\n\n  function mousewheel( event ) {\n    if ( _this.enabled === false ) return;\n\n    event.preventDefault();\n    event.stopPropagation();\n\n    switch ( event.deltaMode ) {\n      case 2:\n        // Zoom in pages\n        _zoomStart.y -= event.deltaY * 0.025;\n        break;\n\n      case 1:\n        // Zoom in lines\n        _zoomStart.y -= event.deltaY * 0.01;\n        break;\n\n      default:\n        // undefined, 0, assume pixels\n        _zoomStart.y -= event.deltaY * 0.00025;\n        break;\n    }\n\n    _this.dispatchEvent( startEvent );\n    _this.dispatchEvent( endEvent );\n  }\n\n  function touchstart( event ) {\n    if ( _this.enabled === false ) return;\n\n    switch ( event.touches.length ) {\n      case 1:\n        _state = STATE.TOUCH_ROTATE;\n        _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );\n        _movePrev.copy( _moveCurr );\n        break;\n\n      default: // 2 or more\n        _state = STATE.TOUCH_ZOOM_PAN;\n        var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n        var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n        _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );\n\n        var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;\n        var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;\n        _panStart.copy( getMouseOnScreen( x, y ) );\n        _panEnd.copy( _panStart );\n        break;\n    }\n\n    _this.dispatchEvent( startEvent );\n  }\n\n  function touchmove( event ) {\n    if ( _this.enabled === false ) return;\n\n    event.preventDefault();\n    event.stopPropagation();\n\n    switch ( event.touches.length ) {\n      case 1:\n        _movePrev.copy( _moveCurr );\n        _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );\n        break;\n\n      default: // 2 or more\n        var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n        var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n        _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );\n\n        var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;\n        var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;\n        _panEnd.copy( getMouseOnScreen( x, y ) );\n        break;\n    }\n  }\n\n  function touchend( event ) {\n    if ( _this.enabled === false ) return;\n\n    switch ( event.touches.length ) {\n      case 0:\n        _state = STATE.NONE;\n        break;\n\n      case 1:\n        _state = STATE.TOUCH_ROTATE;\n        _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );\n        _movePrev.copy( _moveCurr );\n        break;\n    }\n\n    _this.dispatchEvent( endEvent );\n  }\n\n  function contextmenu( event ) {\n    event.preventDefault();\n  }\n\n  this.dispose = function() {\n    this.domElement.removeEventListener( 'contextmenu', contextmenu, false );\n    this.domElement.removeEventListener( 'mousedown', mousedown, false );\n    this.domElement.removeEventListener( 'wheel', mousewheel, false );\n\n    this.domElement.removeEventListener( 'touchstart', touchstart, false );\n    this.domElement.removeEventListener( 'touchend', touchend, false );\n    this.domElement.removeEventListener( 'touchmove', touchmove, false );\n\n    document.removeEventListener( 'mousemove', mousemove, false );\n    document.removeEventListener( 'mouseup', mouseup, false );\n\n    window.removeEventListener( 'keydown', keydown, false );\n    window.removeEventListener( 'keyup', keyup, false );\n  };\n\n  this.domElement.addEventListener( 'contextmenu', contextmenu, false );\n  this.domElement.addEventListener( 'mousedown', mousedown, false );\n  this.domElement.addEventListener( 'wheel', mousewheel, false );\n\n  this.domElement.addEventListener( 'touchstart', touchstart, false );\n  this.domElement.addEventListener( 'touchend', touchend, false );\n  this.domElement.addEventListener( 'touchmove', touchmove, false );\n\n  window.addEventListener( 'keydown', keydown, false );\n  window.addEventListener( 'keyup', keyup, false );\n\n  this.handleResize();\n\n  // force an update at start\n  this.update();\n};\n\nTHREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );\nTHREE.TrackballControls.prototype.constructor = THREE.TrackballControls;\n"
  },
  {
    "path": "packages/driver-weex/CHANGELOG.md",
    "content": "## Changelog\n\n### v2.1.0\n\n- Support weex v2\n\n### v2.0.2\n\n- Bump version\n\n### v2.0.1\n\n- Use `style-unit` convert `rpx`\n"
  },
  {
    "path": "packages/driver-weex/README.md",
    "content": "# driver-weex\n\n> Weex driver for Rax.\n\n## Install\n\n```bash\n$ npm install --save driver-weex\n```\n\n## Use\n\n```jsx\nimport {createElement, Component, render} from 'rax';\nimport * as WeexDriver from 'driver-weex';\n\nclass Example extends Component {\n  render() {\n    return (\n      <div>\n        <img width=\"560\" height=\"560\" src=\"https://img.alicdn.com/tps/TB1z.55OFXXXXcLXXXXXXXXXXXX-560-560.jpg\" />\n      </div>\n    );\n  }\n}\n\nrender(<Example />, null, {\n  driver: WeexDriver\n});\n```\n"
  },
  {
    "path": "packages/driver-weex/package.json",
    "content": "{\n  \"name\": \"driver-weex\",\n  \"version\": \"2.1.0\",\n  \"description\": \"Weex driver for Rax\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"module\": \"es/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"dependencies\": {\n    \"driver-dom\": \"^2.0.5\",\n    \"style-unit\": \"^3.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/driver-weex/src/index.d.ts",
    "content": "// Driver spec: https://github.com/alibaba/rax/blob/master/docs/en-US/driver-spec.md\ndeclare namespace Driver {\n  function createBody(): void;\n  function createEmpty(component: any): void;\n  function createText(): void;\n  function updateText(node: any, text: any)\n  function createElement(type: any, props: any, component: any)\n  function appendChild(node: any, parent: any)\n  function removeChild(node: any, parent: any)\n  function replaceChild(newChild: any, oldChild: any, parent: any)\n  function insertAfter(node: any, after: any, parent: any)\n  function insertBefore(node: any, before: any, parent: any)\n  function addEventListener(node: any, eventName: any, eventHandler: any)\n  function removeEventListener(node: any, eventName: any, eventHandler: any)\n  function setAttribute(node: any, propKey: any, propValue: any)\n  function removeAttribute(node: any, propKey: any)\n  function setStyle(node: any, styleObject: any)\n}\n\nexport default Driver;\n"
  },
  {
    "path": "packages/driver-weex/src/index.js",
    "content": "import { setRpx, convertUnit } from 'style-unit';\nimport * as DriverDOM from 'driver-dom';\n\n// Use driver-dom in Weex V2\n/* global __weex_v2__ */\nconst isWeexV2 = typeof __weex_v2__ === 'object';\n\nconst STYLE = 'style';\nconst ID = 'id';\nconst TEXT = 'text';\nconst CHILDREN = 'children';\nconst EVENT_PREFIX_REGEXP = /^on[A-Z]/;\nconst ARIA_PREFIX_REGEXP = /^aria-/;\nconst HYPHEN_REGEXP = /\\-(\\w)/;\nconst EMPTY = '';\n\nfunction updateWeexTextValue(node) {\n  const value = node.children.map(function(child) {\n    // Comment node type\n    return child.nodeType === 8 ? child.value : EMPTY;\n  }).join(EMPTY);\n\n  node.setAttr('value', value);\n}\n\nconst nodeMaps = {};\n/* global __weex_document__ */\nconst weexDocument = typeof __weex_document__ === 'object' ?\n  __weex_document__ : typeof document === 'object' ?\n    document : null;\n\nexport function getElementById(id) {\n  if (isWeexV2) {\n    return document.getElementById(id);\n  }\n  return nodeMaps[id];\n}\n\nexport function createBody(type, props) {\n  if (isWeexV2) {\n    return DriverDOM.createBody();\n  }\n  if (weexDocument.body) {\n    return weexDocument.body;\n  }\n\n  const documentElement = weexDocument.documentElement;\n  const body = weexDocument.createBody(type, props);\n  documentElement.appendChild(body);\n\n  return body;\n}\n\nexport function createComment(content) {\n  return weexDocument.createComment(content);\n}\n\nexport function createEmpty(component) {\n  if (isWeexV2) {\n    return DriverDOM.createEmpty(component);\n  }\n  return createComment(EMPTY);\n}\n\nexport function createText(text, component) {\n  if (isWeexV2) {\n    return DriverDOM.createText(text, component);\n  }\n  // Use comment node type mock text node\n  return createComment(text);\n}\n\nexport function updateText(node, text) {\n  if (isWeexV2) {\n    return DriverDOM.updateText(node, text);\n  }\n  node.value = text;\n  updateWeexTextValue(node.parentNode);\n}\n\nexport function createElement(type, props, component) {\n  if (isWeexV2) {\n    return DriverDOM.createElement(type, props, component, true);\n  }\n  const style = {};\n  props = props || {};\n  const originStyle = props.style;\n  if (originStyle) {\n    for (let prop in originStyle) {\n      style[prop] = convertUnit(originStyle[prop], prop);\n    }\n  }\n\n  const node = weexDocument.createElement(type, {\n    style\n  });\n\n  for (let prop in props) {\n    let value = props[prop];\n    if (prop === CHILDREN) {\n      continue;\n    }\n    if (value != null) {\n      if (prop === STYLE) {\n        continue;\n      } else if (EVENT_PREFIX_REGEXP.test(prop)) {\n        let eventName = prop.slice(2).toLowerCase();\n        addEventListener(node, eventName, value, props);\n      } else {\n        setAttribute(node, prop, value);\n      }\n    }\n  }\n\n  return node;\n}\n\nexport function appendChild(node, parent) {\n  if (isWeexV2) {\n    return DriverDOM.appendChild(node, parent);\n  }\n  parent.appendChild(node);\n\n  if (parent.type === TEXT) {\n    updateWeexTextValue(parent);\n  }\n}\n\nexport function removeChild(node, parent) {\n  if (isWeexV2) {\n    return DriverDOM.removeChild(node, parent);\n  }\n  parent = parent || node.parentNode;\n  let id = node.attr && node.attr[ID];\n  if (id != null) {\n    nodeMaps[id] = null;\n  }\n\n  parent.removeChild(node);\n\n  if (parent.type === TEXT) {\n    updateWeexTextValue(parent);\n  }\n}\n\nexport function replaceChild(newChild, oldChild, parent) {\n  if (isWeexV2) {\n    return DriverDOM.replaceChild(newChild, oldChild, parent);\n  }\n  parent = parent || oldChild.parentNode;\n  let previousSibling = oldChild.previousSibling;\n  let nextSibling = oldChild.nextSibling;\n  removeChild(oldChild, parent);\n\n  if (previousSibling) {\n    insertAfter(newChild, previousSibling, parent);\n  } else if (nextSibling) {\n    insertBefore(newChild, nextSibling, parent);\n  } else {\n    appendChild(newChild, parent);\n  }\n}\n\nexport function insertAfter(node, after, parent) {\n  if (isWeexV2) {\n    return DriverDOM.insertAfter(node, after, parent);\n  }\n  parent = parent || after.parentNode;\n  parent.insertAfter(node, after);\n\n  if (parent.type === TEXT) {\n    updateWeexTextValue(parent);\n  }\n}\n\nexport function insertBefore(node, before, parent) {\n  if (isWeexV2) {\n    return DriverDOM.insertBefore(node, before, parent);\n  }\n  parent = parent || before.parentNode;\n  parent.insertBefore(node, before);\n\n  if (parent.type === TEXT) {\n    updateWeexTextValue(parent);\n  }\n}\n\nexport function addEventListener(node, eventName, eventHandler, props) {\n  if (isWeexV2) {\n    return DriverDOM.addEventListener(node, eventName, eventHandler);\n  }\n  // https://github.com/apache/incubator-weex/blob/master/runtime/vdom/Element.js#L421\n  let params = props[eventName + 'EventParams'];\n  return node.addEvent(eventName, eventHandler, params);\n}\n\nexport function removeEventListener(node, eventName, eventHandler) {\n  if (isWeexV2) {\n    return DriverDOM.removeEventListener(node, eventName, eventHandler);\n  }\n  return node.removeEvent(eventName, eventHandler);\n}\n\nexport function removeAttribute(node, propKey, propValue) {\n  if (isWeexV2) {\n    return DriverDOM.removeAttribute(node, propKey);\n  }\n  if (propKey == ID) {\n    nodeMaps[propValue] = null;\n  }\n  // Weex native will crash when pass null value\n  return node.setAttr(propKey, undefined, false);\n}\n\nexport function setAttribute(node, propKey, propValue, isSvg) {\n  if (isWeexV2) {\n    return DriverDOM.setAttribute(node, propKey, propValue, isSvg);\n  }\n  if (propKey == ID) {\n    nodeMaps[propValue] = node;\n  }\n\n  // Weex only support `ariaLabel` format, convert `aria-label` format to camelcase\n  if (ARIA_PREFIX_REGEXP.test(propKey)) {\n    propKey = propKey.replace(HYPHEN_REGEXP, function(m, p) {\n      return p.toUpperCase();\n    });\n  }\n\n  return node.setAttr(propKey, propValue, false);\n}\n\nexport function setStyle(node, style) {\n  if (isWeexV2) {\n    return DriverDOM.setStyle(node, style, true);\n  }\n  for (let prop in style) {\n    // Translate `rpx` to weex `px`\n    style[prop] = convertUnit(style[prop], prop);\n  }\n  node.setStyles(style);\n}\n\nexport function beforeRender() {\n  // Turn off batched updates\n  weexDocument.open();\n\n  // Set `rpx` unit converter\n  setRpx(1);\n}\n\nexport function afterRender() {\n  if (weexDocument.listener && weexDocument.listener.createFinish) {\n    weexDocument.listener.createFinish();\n  }\n\n  // Turn on batched updates\n  weexDocument.close();\n}\n"
  },
  {
    "path": "packages/mobx-rax/CHANGELOG.md",
    "content": "# Changelog\n\n## v1.0.1\n\n- Chore: add `@babel/runtime` as dependency\n"
  },
  {
    "path": "packages/mobx-rax/README.md",
    "content": "# mobx-rax [![npm](https://img.shields.io/npm/v/mobx-rax.svg)](https://www.npmjs.com/package/mobx-rax)\n"
  },
  {
    "path": "packages/mobx-rax/package.json",
    "content": "{\n  \"name\": \"mobx-rax\",\n  \"version\": \"1.0.1\",\n  \"description\": \"Official Rax bindings for mobx.\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"dependencies\": {\n    \"hoist-non-react-statics\": \"^2.5.0\",\n    \"rax\": \"^1.0.0\",\n    \"rax-children\": \"^1.0.0\",\n    \"rax-find-dom-node\": \"^1.0.0\",\n    \"react-lifecycles-compat\": \"^3.0.4\",\n    \"@babel/runtime\": \"^7.14.6\"\n  },\n  \"peerDependencies\": {\n    \"mobx\": \"^4.0.0 || ^5.0.0\",\n    \"rax\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"rax-test-renderer\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/mobx-rax/src/Provider.js",
    "content": "import { Component } from 'rax';\nimport Children from 'rax-children';\nimport { polyfill } from 'react-lifecycles-compat';\nimport * as PropTypes from './propTypes';\n\nconst specialReactKeys = { children: true, key: true, ref: true };\n\nclass Provider extends Component {\n    static contextTypes = {\n      mobxStores: PropTypes.objectOrObservableObject\n    }\n\n    static childContextTypes = {\n      mobxStores: PropTypes.objectOrObservableObject.isRequired\n    }\n\n    constructor(props, context) {\n      super(props, context);\n      this.state = props || {};\n    }\n\n    isReactComponent() {}\n\n    render() {\n      return Children.only(this.props.children);\n    }\n\n    getChildContext() {\n      const stores = {};\n      // inherit stores\n      const baseStores = this.context.mobxStores;\n      if (baseStores)\n        for (let key in baseStores) {\n          stores[key] = baseStores[key];\n        }\n        // add own stores\n      for (let key in this.state)\n        if (!specialReactKeys[key] && key !== 'suppressChangedStoreWarning')\n          stores[key] = this.props[key];\n      return {\n        mobxStores: stores\n      };\n    }\n\n    static getDerivedStateFromProps(nextProps, prevState) {\n      if (!nextProps) return null;\n      if (!prevState) return nextProps;\n\n      // Maybe this warning is too aggressive?\n      if (Object.keys(nextProps).length !== Object.keys(prevState).length)\n        console.warn(\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      if (!nextProps.suppressChangedStoreWarning)\n        for (let key in nextProps)\n          if (!specialReactKeys[key] && prevState[key] !== nextProps[key])\n            console.warn(\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      return nextProps;\n    }\n}\n\n// TODO: kill in next major\npolyfill(Provider);\n\nexport default Provider;\n"
  },
  {
    "path": "packages/mobx-rax/src/index.js",
    "content": "import { spy, configure, getDebugName } from 'mobx';\nimport { Component } from 'rax';\n// import { unstable_batchedUpdates as rdBatched } from \"react-dom\"\n// import { unstable_batchedUpdates as rnBatched } from \"react-native\"\n\nif (!Component) throw new Error('mobx-rax requires React to be available');\nif (!spy) throw new Error('mobx-rax requires mobx to be available');\n\n// if (typeof rdBatched === \"function\") configure({ reactionScheduler: rdBatched })\n// else if (typeof rnBatched === \"function\") configure({ reactionScheduler: rnBatched })\n\nexport {\n  observer,\n  Observer,\n  renderReporter,\n  componentByNodeRegistry as componentByNodeRegistery,\n  componentByNodeRegistry,\n  trackComponents,\n  useStaticRendering\n} from './observer';\n\nexport { default as Provider } from './Provider';\nexport { default as inject } from './inject';\n\nimport * as propTypes from './propTypes';\n\nexport { propTypes };\nexport { propTypes as PropTypes };\n\nimport { renderReporter, componentByNodeRegistry, trackComponents, errorsReporter } from './observer';\n\nexport const onError = fn => errorsReporter.on(fn);\n\n/* DevTool support */\n// See: https://github.com/andykog/mobx-devtools/blob/d8976c24b8cb727ed59f9a0bc905a009df79e221/src/backend/installGlobalHook.js\n\n/* global __MOBX_DEVTOOLS_GLOBAL_HOOK__ */\nif (typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__ === 'object') {\n  const mobx = { spy, extras: { getDebugName } };\n  const mobxReact = {\n    renderReporter,\n    componentByNodeRegistry,\n    componentByNodeRegistery: componentByNodeRegistry,\n    trackComponents\n  };\n  __MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobxReact(mobxReact, mobx);\n}\n"
  },
  {
    "path": "packages/mobx-rax/src/inject.js",
    "content": "import { Component, createElement } from 'rax';\nimport hoistStatics from 'hoist-non-react-statics';\nimport * as PropTypes from './propTypes';\nimport { observer } from './observer';\nimport { isStateless } from './utils/utils';\n\nconst injectorContextTypes = {\n  mobxStores: PropTypes.objectOrObservableObject\n};\nObject.seal(injectorContextTypes);\n\nconst proxiedInjectorProps = {\n  contextTypes: {\n    get: function() {\n      return injectorContextTypes;\n    },\n    set: function(_) {\n      console.warn(\n        'Mobx Injector: you are trying to attach `contextTypes` on an component decorated with `inject` (or `observer`) HOC. Please specify the contextTypes on the wrapped component instead. It is accessible through the `wrappedComponent`'\n      );\n    },\n    configurable: true,\n    enumerable: false\n  },\n  isMobxInjector: {\n    value: true,\n    writable: true,\n    configurable: true,\n    enumerable: true\n  }\n};\n\n/**\n * Store Injection\n */\nfunction createStoreInjector(grabStoresFn, component, injectNames) {\n  let displayName =\n        'inject-' +\n        (component.displayName ||\n            component.name ||\n            component.constructor && component.constructor.name ||\n            'Unknown');\n  if (injectNames) displayName += '-with-' + injectNames;\n\n  class Injector extends Component {\n        static displayName = displayName\n\n        storeRef = instance => {\n          this.wrappedInstance = instance;\n        }\n\n        render() {\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          let newProps = {};\n          for (let key in this.props)\n            if (this.props.hasOwnProperty(key)) {\n              newProps[key] = this.props[key];\n            }\n          var additionalProps =\n                grabStoresFn(this.context.mobxStores || {}, newProps, this.context) || {};\n          for (let key in additionalProps) {\n            newProps[key] = additionalProps[key];\n          }\n\n          if (!isStateless(component)) {\n            newProps.ref = this.storeRef;\n          }\n\n          return createElement(component, newProps);\n        }\n  }\n\n  // Static fields from component should be visible on the generated Injector\n  hoistStatics(Injector, component);\n\n  Injector.wrappedComponent = component;\n  Object.defineProperties(Injector, proxiedInjectorProps);\n\n  return Injector;\n}\n\nfunction grabStoresByName(storeNames) {\n  return function(baseStores, nextProps) {\n    storeNames.forEach(function(storeName) {\n      if (\n        storeName in nextProps // prefer props over stores\n      )\n        return;\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      nextProps[storeName] = baseStores[storeName];\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 */\nexport default function inject(/* fn(stores, nextProps) or ...storeNames */) {\n  let grabStoresFn;\n  if (typeof arguments[0] === 'function') {\n    grabStoresFn = arguments[0];\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 = [];\n    for (let i = 0; i < arguments.length; i++) storeNames[i] = arguments[i];\n    grabStoresFn = grabStoresByName(storeNames);\n    return function(componentClass) {\n      return createStoreInjector(grabStoresFn, componentClass, storeNames.join('-'));\n    };\n  }\n}\n"
  },
  {
    "path": "packages/mobx-rax/src/observer.js",
    "content": "import {createElement, Component, PureComponent} from 'rax';\nimport baseFindDOMNode from 'rax-find-dom-node';\nimport hoistStatics from 'hoist-non-react-statics';\nimport { createAtom, Reaction, _allowStateChanges, $mobx } from 'mobx';\nimport EventEmitter from './utils/EventEmitter';\nimport inject from './inject';\n\nconst mobxAdminProperty = $mobx || '$mobx';\n\n/**\n * dev tool support\n */\nlet isDevtoolsEnabled = false;\n\nlet isUsingStaticRendering = false;\n\nlet warnedAboutObserverInjectDeprecation = false;\n\n// WeakMap<Node, Object>;\nexport const componentByNodeRegistry = typeof WeakMap !== 'undefined' ? new WeakMap() : undefined;\nexport const renderReporter = new EventEmitter();\n\nfunction createSymbol(name) {\n  if (typeof Symbol === 'function') {\n    return Symbol(name);\n  }\n  return `$mobxReactProp$${name}${Math.random()}`;\n}\n\nconst skipRenderKey = createSymbol('skipRender');\nconst isForcingUpdateKey = createSymbol('isForcingUpdate');\n\n/**\n * Helper to set `prop` to `this` as non-enumerable (hidden prop)\n * @param target\n * @param prop\n * @param value\n */\nfunction setHiddenProp(target, prop, value) {\n  if (!Object.hasOwnProperty(target, prop)) {\n    Object.defineProperty(target, prop, {\n      enumerable: false,\n      configurable: true,\n      writeable: true,\n      value\n    });\n  } else {\n    target[prop] = value;\n  }\n}\n\nfunction findDOMNode(component) {\n  if (baseFindDOMNode) {\n    try {\n      return baseFindDOMNode(component);\n    } catch (e) {\n      // findDOMNode will throw in react-test-renderer, see:\n      // See https://github.com/mobxjs/mobx-react/issues/216\n      // Is there a better heuristic?\n      return null;\n    }\n  }\n  return null;\n}\n\nfunction reportRendering(component) {\n  const node = findDOMNode(component);\n  if (node && componentByNodeRegistry) componentByNodeRegistry.set(node, component);\n\n  renderReporter.emit({\n    event: 'render',\n    renderTime: component.__$mobRenderEnd - component.__$mobRenderStart,\n    totalTime: Date.now() - component.__$mobRenderStart,\n    component: component,\n    node: node\n  });\n}\n\nexport function trackComponents() {\n  if (typeof WeakMap === 'undefined')\n    throw new Error('[mobx-react] tracking components is not supported in this browser.');\n  if (!isDevtoolsEnabled) isDevtoolsEnabled = true;\n}\n\nexport function useStaticRendering(useStaticRendering) {\n  isUsingStaticRendering = useStaticRendering;\n}\n\n/**\n * Errors reporter\n */\n\nexport const errorsReporter = new EventEmitter();\n\n/**\n * Utilities\n */\n\nfunction patch(target, funcName, runMixinFirst = false) {\n  const base = target[funcName];\n  const mixinFunc = reactiveMixin[funcName];\n  const f = !base\n    ? mixinFunc\n    : runMixinFirst === true\n      ? function() {\n        mixinFunc.apply(this, arguments);\n        base.apply(this, arguments);\n      }\n      : function() {\n        base.apply(this, arguments);\n        mixinFunc.apply(this, arguments);\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 shallowEqual(objA, objB) {\n  // From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js\n  if (is(objA, objB)) return true;\n  if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {\n    return false;\n  }\n  const keysA = Object.keys(objA);\n  const keysB = Object.keys(objB);\n  if (keysA.length !== keysB.length) return false;\n  for (let i = 0; i < keysA.length; i++) {\n    if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {\n      return false;\n    }\n  }\n  return true;\n}\n\nfunction is(x, y) {\n  // From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js\n  if (x === y) {\n    return x !== 0 || 1 / x === 1 / y;\n  } else {\n    return x !== x && y !== y;\n  }\n}\n\nfunction makeComponentReactive(render) {\n  if (isUsingStaticRendering === true) return render.call(this);\n\n  function reactiveRender() {\n    isRenderingPending = false;\n    let exception = undefined;\n    let rendering = undefined;\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  // Generate friendly name for debugging\n  const initialName =\n        this.displayName ||\n        this.name ||\n        this.constructor && (this.constructor.displayName || this.constructor.name) ||\n        '<component>';\n  const rootNodeID =\n        this._reactInternalInstance && this._reactInternalInstance._rootNodeID ||\n        this._reactInternalInstance && this._reactInternalInstance._debugID ||\n        this._reactInternalFiber && this._reactInternalFiber._debugID;\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  setHiddenProp(this, skipRenderKey, 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  setHiddenProp(this, isForcingUpdateKey, false);\n\n  // wire up reactive render\n  const baseRender = render.bind(this);\n  let isRenderingPending = false;\n\n  const reaction = new Reaction(`${initialName}#${rootNodeID}.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') this.componentWillReact(); // TODO: wrap in action?\n      if (this.__$mobxIsUnmounted !== true) {\n        // If we are unmounted at this point, componentWillReact() had a side effect causing the component to unmounted\n        // TODO: remove this check? Then react will properly warn about the fact that this should not happen? See #73\n        // However, people also claim this migth happen during unit tests..\n        let hasError = true;\n        try {\n          setHiddenProp(this, isForcingUpdateKey, true);\n          if (!this[skipRenderKey]) Component.prototype.forceUpdate.call(this);\n          hasError = false;\n        } finally {\n          setHiddenProp(this, isForcingUpdateKey, false);\n          if (hasError) reaction.dispose();\n        }\n      }\n    }\n  });\n  reaction.reactComponent = this;\n  reactiveRender[mobxAdminProperty] = reaction;\n  this.render = reactiveRender;\n  return reactiveRender.call(this);\n}\n\n/**\n * ReactiveMixin\n */\nconst reactiveMixin = {\n  componentWillUnmount: function() {\n    if (isUsingStaticRendering === true) return;\n    this.render[mobxAdminProperty] && this.render[mobxAdminProperty].dispose();\n    this.__$mobxIsUnmounted = true;\n    if (isDevtoolsEnabled) {\n      const node = findDOMNode(this);\n      if (node && componentByNodeRegistry) {\n        componentByNodeRegistry.delete(node);\n      }\n      renderReporter.emit({\n        event: 'destroy',\n        component: this,\n        node: node\n      });\n    }\n  },\n\n  componentDidMount: function() {\n    if (isDevtoolsEnabled) {\n      reportRendering(this);\n    }\n  },\n\n  componentDidUpdate: function() {\n    if (isDevtoolsEnabled) {\n      reportRendering(this);\n    }\n  },\n\n  shouldComponentUpdate: function(nextProps, nextState) {\n    if (isUsingStaticRendering) {\n      console.warn(\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 !shallowEqual(this.props, nextProps);\n  }\n};\n\nfunction makeObservableProp(target, propName) {\n  const valueHolderKey = createSymbol(propName + ' value holder');\n  const atomHolderKey = createSymbol(propName + ' atom holder');\n  function getAtom() {\n    if (!this[atomHolderKey]) {\n      setHiddenProp(this, atomHolderKey, createAtom('reactive ' + propName));\n    }\n    return this[atomHolderKey];\n  }\n  Object.defineProperty(target, propName, {\n    configurable: true,\n    enumerable: true,\n    get: function() {\n      getAtom.call(this).reportObserved();\n      return this[valueHolderKey];\n    },\n    set: function set(v) {\n      if (!this[isForcingUpdateKey] && !shallowEqual(this[valueHolderKey], v)) {\n        setHiddenProp(this, valueHolderKey, v);\n        setHiddenProp(this, skipRenderKey, true);\n        getAtom.call(this).reportChanged();\n        setHiddenProp(this, skipRenderKey, false);\n      } else {\n        setHiddenProp(this, valueHolderKey, v);\n      }\n    }\n  });\n}\n\n/**\n * Observer function / decorator\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    // TODO: remove in next major\n    // component needs stores\n    if (!warnedAboutObserverInjectDeprecation) {\n      warnedAboutObserverInjectDeprecation = true;\n      console.warn(\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      return inject.apply(null, arg1)(observer(arg2));\n    }\n  }\n  const componentClass = arg1;\n\n  if (componentClass.isMobxInjector === true) {\n    console.warn(\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  if (componentClass.__proto__ === PureComponent) {\n    console.warn(\n      \"Mobx observer: You are using 'observer' on React.PureComponent. These two achieve two opposite goals and should not be used together\"\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 (\n    typeof componentClass === 'function' &&\n        (!componentClass.prototype || !componentClass.prototype.render) &&\n        !componentClass.isReactClass &&\n        !Component.isPrototypeOf(componentClass)\n  ) {\n    const observerComponent = observer(\n      class extends Component {\n                static displayName = componentClass.displayName || componentClass.name\n                static contextTypes = componentClass.contextTypes\n                static propTypes = componentClass.propTypes\n                static defaultProps = componentClass.defaultProps\n                render() {\n                  return componentClass.call(this, this.props, this.context);\n                }\n      }\n    );\n    hoistStatics(observerComponent, componentClass);\n    return observerComponent;\n  }\n\n  if (!componentClass) {\n    throw new Error(\"Please pass a valid component to 'observer'\");\n  }\n\n  const target = componentClass.prototype || componentClass;\n  mixinLifecycleEvents(target);\n  componentClass.isMobXReactObserver = true;\n  makeObservableProp(target, 'props');\n  makeObservableProp(target, 'state');\n  const baseRender = target.render;\n  target.render = function() {\n    return makeComponentReactive.call(this, baseRender);\n  };\n  return componentClass;\n}\n\nfunction mixinLifecycleEvents(target) {\n  ;['componentDidMount', 'componentWillUnmount', 'componentDidUpdate'].forEach(function(\n    funcName\n  ) {\n    patch(target, funcName);\n  });\n  if (!target.shouldComponentUpdate) {\n    target.shouldComponentUpdate = reactiveMixin.shouldComponentUpdate;\n  } else {\n    if (target.shouldComponentUpdate !== reactiveMixin.shouldComponentUpdate) {\n      // TODO: make throw in next major\n      console.warn(\n        'Use `shouldComponentUpdate` in an `observer` based component breaks the behavior of `observer` and might lead to unexpected results. Manually implementing `sCU` should not be needed when using mobx-react.'\n      );\n    }\n  }\n}\n\nexport const Observer = observer(({ children, inject: observerInject, render }) => {\n  const component = children || render;\n  if (typeof component === 'undefined') {\n    return null;\n  }\n  if (!observerInject) {\n    return component();\n  }\n  // TODO: remove in next major\n  console.warn(\n    '<Observer inject=.../> is no longer supported. Please use inject on the enclosing component instead'\n  );\n  const InjectComponent = inject(observerInject)(component);\n  return <InjectComponent />;\n});\n\nObserver.displayName = 'Observer';\n\nconst ObserverPropsCheck = (props, key, componentName, location, propFullName) => {\n  const extraKey = key === 'children' ? 'render' : 'children';\n  if (typeof props[key] === 'function' && typeof props[extraKey] === 'function') {\n    return new Error(\n      'Invalid prop,do not use children and render in the same time in`' + componentName\n    );\n  }\n\n  if (typeof props[key] === 'function' || typeof props[extraKey] === 'function') {\n    return;\n  }\n  return new Error(\n    'Invalid prop `' +\n            propFullName +\n            '` of type `' +\n            typeof props[key] +\n            '` supplied to' +\n            ' `' +\n            componentName +\n            '`, expected `function`.'\n  );\n};\n\nObserver.propTypes = {\n  render: ObserverPropsCheck,\n  children: ObserverPropsCheck\n};\n"
  },
  {
    "path": "packages/mobx-rax/src/propTypes.js",
    "content": "import { isObservableArray, isObservableObject, isObservableMap, untracked } from 'mobx';\n\n// Copied from React.PropTypes\nfunction createChainableTypeChecker(validate) {\n  function checkType(\n    isRequired,\n    props,\n    propName,\n    componentName,\n    location,\n    propFullName,\n    ...rest\n  ) {\n    return untracked(() => {\n      componentName = componentName || '<<anonymous>>';\n      propFullName = propFullName || propName;\n      if (props[propName] == null) {\n        if (isRequired) {\n          const actual = props[propName] === null ? 'null' : 'undefined';\n          return new Error(\n            'The ' +\n                            location +\n                            ' `' +\n                            propFullName +\n                            '` is marked as required ' +\n                            'in `' +\n                            componentName +\n                            '`, but its value is `' +\n                            actual +\n                            '`.'\n          );\n        }\n        return null;\n      } else {\n        return validate(props, propName, componentName, location, propFullName, ...rest);\n      }\n    });\n  }\n\n  const chainedCheckType = checkType.bind(null, false);\n  chainedCheckType.isRequired = checkType.bind(null, true);\n  return chainedCheckType;\n}\n\n// Copied from React.PropTypes\nfunction isSymbol(propType, propValue) {\n  // Native Symbol.\n  if (propType === 'symbol') {\n    return true;\n  }\n\n  // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'\n  if (propValue['@@toStringTag'] === 'Symbol') {\n    return true;\n  }\n\n  // Fallback for non-spec compliant Symbols which are polyfilled.\n  if (typeof Symbol === 'function' && propValue instanceof Symbol) {\n    return true;\n  }\n\n  return false;\n}\n\n// Copied from React.PropTypes\nfunction getPropType(propValue) {\n  const propType = typeof propValue;\n  if (Array.isArray(propValue)) {\n    return 'array';\n  }\n  if (propValue instanceof RegExp) {\n    // Old webkits (at least until Android 4.0) return 'function' rather than\n    // 'object' for typeof a RegExp. We'll normalize this here so that /bla/\n    // passes PropTypes.object.\n    return 'object';\n  }\n  if (isSymbol(propType, propValue)) {\n    return 'symbol';\n  }\n  return propType;\n}\n\n// This handles more types than `getPropType`. Only used for error messages.\n// Copied from React.PropTypes\nfunction getPreciseType(propValue) {\n  const propType = getPropType(propValue);\n  if (propType === 'object') {\n    if (propValue instanceof Date) {\n      return 'date';\n    } else if (propValue instanceof RegExp) {\n      return 'regexp';\n    }\n  }\n  return propType;\n}\n\nfunction createObservableTypeCheckerCreator(allowNativeType, mobxType) {\n  return createChainableTypeChecker(function(\n    props,\n    propName,\n    componentName,\n    location,\n    propFullName\n  ) {\n    return untracked(() => {\n      if (allowNativeType) {\n        if (getPropType(props[propName]) === mobxType.toLowerCase()) return null;\n      }\n      let mobxChecker;\n      switch (mobxType) {\n        case 'Array':\n          mobxChecker = isObservableArray;\n          break;\n        case 'Object':\n          mobxChecker = isObservableObject;\n          break;\n        case 'Map':\n          mobxChecker = isObservableMap;\n          break;\n        default:\n          throw new Error(`Unexpected mobxType: ${mobxType}`);\n      }\n      const propValue = props[propName];\n      if (!mobxChecker(propValue)) {\n        const preciseType = getPreciseType(propValue);\n        const nativeTypeExpectationMessage = allowNativeType\n          ? ' or javascript `' + mobxType.toLowerCase() + '`'\n          : '';\n        return new Error(\n          'Invalid prop `' +\n                        propFullName +\n                        '` of type `' +\n                        preciseType +\n                        '` supplied to' +\n                        ' `' +\n                        componentName +\n                        '`, expected `mobx.Observable' +\n                        mobxType +\n                        '`' +\n                        nativeTypeExpectationMessage +\n                        '.'\n        );\n      }\n      return null;\n    });\n  });\n}\n\nfunction createObservableArrayOfTypeChecker(allowNativeType, typeChecker) {\n  return createChainableTypeChecker(function(\n    props,\n    propName,\n    componentName,\n    location,\n    propFullName,\n    ...rest\n  ) {\n    return untracked(() => {\n      if (typeof typeChecker !== 'function') {\n        return new Error(\n          'Property `' +\n                        propFullName +\n                        '` of component `' +\n                        componentName +\n                        '` has ' +\n                        'invalid PropType notation.'\n        );\n      }\n      let error = createObservableTypeCheckerCreator(allowNativeType, 'Array')(\n        props,\n        propName,\n        componentName\n      );\n      if (error instanceof Error) return error;\n      const propValue = props[propName];\n      for (let i = 0; i < propValue.length; i++) {\n        error = typeChecker(\n          propValue,\n          i,\n          componentName,\n          location,\n          propFullName + '[' + i + ']',\n          ...rest\n        );\n        if (error instanceof Error) return error;\n      }\n      return null;\n    });\n  });\n}\n\nexport const observableArray = createObservableTypeCheckerCreator(false, 'Array');\nexport const observableArrayOf = createObservableArrayOfTypeChecker.bind(null, false);\nexport const observableMap = createObservableTypeCheckerCreator(false, 'Map');\nexport const observableObject = createObservableTypeCheckerCreator(false, 'Object');\nexport const arrayOrObservableArray = createObservableTypeCheckerCreator(true, 'Array');\nexport const arrayOrObservableArrayOf = createObservableArrayOfTypeChecker.bind(null, true);\nexport const objectOrObservableObject = createObservableTypeCheckerCreator(true, 'Object');\n"
  },
  {
    "path": "packages/mobx-rax/src/utils/EventEmitter.js",
    "content": "export default class EventEmitter {\n    listeners = []\n\n    on(cb) {\n      this.listeners.push(cb);\n      return () => {\n        const index = this.listeners.indexOf(cb);\n        if (index !== -1) this.listeners.splice(index, 1);\n      };\n    }\n\n    emit(data) {\n      this.listeners.forEach(fn => fn(data));\n    }\n}\n"
  },
  {
    "path": "packages/mobx-rax/src/utils/utils.js",
    "content": "export function isStateless(component) {\n  // `function() {}` has prototype, but `() => {}` doesn't\n  // `() => {}` via Babel has prototype too.\n  return !(component.prototype && component.prototype.render);\n}\n"
  },
  {
    "path": "packages/rax/.npmignore",
    "content": "node_modules\n*.log\nbuild\n"
  },
  {
    "path": "packages/rax/CHANGELOG.md",
    "content": "## CHANGELOG\n\n### 1.2.3\n\n- chore: move the configuration not related to rendering to `inject` method, others move to `injectRenderOptions` method\n\n### 1.2.2\n\n- fix: `lib/compat` bundle error path\n\n### 1.2.1\n\n- refactor: change output result format, avoid mixing `IIFE` and `CJS`\n- chore: avoid throw error when update unmounted component\n- fix: add error message to `getDerivedStateFromError` hook\n"
  },
  {
    "path": "packages/rax/README.md",
    "content": "# rax [![npm](https://img.shields.io/npm/v/rax.svg)](https://www.npmjs.com/package/rax) [![Dependency Status](https://david-dm.org/alibaba/rax.svg?path=packages/rax)](https://david-dm.org/alibaba/rax.svg?path=packages/rax) [![Known Vulnerabilities](https://snyk.io/test/npm/rax/badge.svg)](https://snyk.io/test/npm/rax)\n\n> A universal React-compatible render engine\n\n## Install\n\n```sh\n$ npm install --save rax\n```\n\n### With TypeScript\n\n```sh\n$ npm install --save-dev @types/rax\n```\n\n## Usage\n\n```jsx\nimport {createElement, render} from 'rax';\nimport * as DriverDOM from 'driver-dom';\n\nfunction MyComponent() {\n  return <div>Hello World</div>;\n}\n\nrender(<MyComponent />, document.body, { driver: DriverDOM });\n```"
  },
  {
    "path": "packages/rax/index.js",
    "content": "if (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/rax.min.js');\n} else {\n  module.exports = require('./dist/rax.js');\n}\n"
  },
  {
    "path": "packages/rax/package.json",
    "content": "{\n  \"name\": \"rax\",\n  \"version\": \"1.2.3\",\n  \"description\": \"A universal React-compatible render engine.\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"devDependencies\": {\n    \"driver-server\": \"^1.0.0\"\n  },\n  \"dependencies\": {\n    \"@babel/runtime\": \"^7.2.0\",\n    \"prop-types\": \"^15.7.2\",\n    \"rax-children\": \"^1.0.0\",\n    \"rax-clone-element\": \"^1.0.0\",\n    \"rax-create-factory\": \"^1.0.0\",\n    \"rax-is-valid-element\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/__tests__/asyncUpdate.js",
    "content": "/* @jsx createElement */\n\nimport createElement from '../createElement';\nimport Component from '../vdom/component';\nimport render from '../render';\nimport Host from '../vdom/host';\nimport ServerDriver from 'driver-server';\nimport { useState, useEffect } from '../hooks';\n\ndescribe('update unmounted component', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('should warn about class component', () => {\n    const container = createNodeElement('div');\n    let destroyChild;\n\n    class Child extends Component {\n      state = {\n        name: 'hello'\n      }\n      componentDidMount() {\n        setTimeout(() => {\n          this.setState({\n            name: 'work'\n          });\n        }, 1000);\n      }\n      render() {\n        return <div>{this.state.name}</div>;\n      }\n    }\n\n    class App extends Component {\n      state = {\n        showChild: true\n      }\n      componentDidMount() {\n        destroyChild = () => {\n          this.setState({\n            showChild: false\n          });\n        };\n      }\n      render() {\n        return (<div>\n          { this.state.showChild ? <Child /> : null }\n        </div>);\n      }\n    }\n\n    expect(() => {\n      render(<App />, container);\n      destroyChild();\n      jest.runAllTimers();\n    }).toWarnDev(\"Warning: Can't perform a Rax state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.\", { withoutStack: true });\n  });\n\n  it('should warn about function component', () => {\n    const container = createNodeElement('div');\n    let destroyChild;\n\n    function Child() {\n      const [name, setName] = useState('hello');\n      useEffect(() => {\n        setTimeout(() => {\n          setName('world');\n        }, 1000);\n      }, []);\n      return <div>{name}</div>;\n    }\n\n    class App extends Component {\n      state = {\n        showChild: true\n      }\n      componentDidMount() {\n        destroyChild = () => {\n          this.setState({\n            showChild: false\n          });\n        };\n      }\n      render() {\n        return (<div>\n          { this.state.showChild ? <Child /> : null }\n        </div>);\n      }\n    }\n\n    expect(() => {\n      render(<App />, container);\n      destroyChild();\n      jest.runAllTimers();\n    }).toWarnDev(\"Warning: Can't perform a Rax state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.\", { withoutStack: true });\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/__tests__/createContext.js",
    "content": "/* @jsx createElement */\n\nimport Component from '../vdom/component';\nimport createElement from '../createElement';\nimport Host from '../vdom/host';\nimport render from '../render';\nimport ServerDriver from 'driver-server';\nimport createContext from '../createContext';\nimport createRef from '../createRef';\nimport { useState } from '../hooks';\n\ndescribe('createContext', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('simple mount and update', () => {\n    const container = createNodeElement('div');\n    const Context = createContext(1);\n\n    function Consumer(props) {\n      return (\n        <Context.Consumer>\n          {value => <span key={value}>{value}</span>}\n        </Context.Consumer>\n      );\n    }\n\n    function App(props) {\n      return (\n        <Context.Provider value={props.value}>\n          <Consumer />\n        </Context.Provider>\n      );\n    }\n\n    render(<App value={2} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('2');\n\n    // Update\n    render(<App value={3} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('3');\n  });\n\n  it('multiple consumers in different branches', () => {\n    const container = createNodeElement('div');\n    const Context = createContext(1);\n\n    function Provider(props) {\n      return (\n        <Context.Consumer>\n          {contextValue => (\n            // Multiply previous context value by 2, unless prop overrides\n            <Context.Provider value={props.value || contextValue * 2}>\n              {props.children}\n            </Context.Provider>\n          )}\n        </Context.Consumer>\n      );\n    }\n\n    function Consumer(props) {\n      return (\n        <Context.Consumer>\n          {value => <span>{value}</span>}\n        </Context.Consumer>\n      );\n    }\n\n    class Indirection extends Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n\n    function App(props) {\n      return (\n        <Provider value={props.value}>\n          <Indirection>\n            <Indirection>\n              <Consumer />\n            </Indirection>\n            <Indirection>\n              <Provider>\n                <Consumer />\n              </Provider>\n            </Indirection>\n          </Indirection>\n        </Provider>\n      );\n    }\n\n    render(<App value={2} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('2');\n    expect(container.childNodes[1].childNodes[0].data).toEqual('4');\n\n    // Update\n    render(<App value={3} />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toEqual('3');\n    expect(container.childNodes[1].childNodes[0].data).toEqual('6');\n\n    // Another update\n    render(<App value={4} />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toEqual('4');\n    expect(container.childNodes[1].childNodes[0].data).toEqual('8');\n  });\n\n  it('Consumer should render correct when its owner props update', () => {\n    const container = createNodeElement('div');\n    const Context = createContext(1);\n    class Indirection extends Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n    class Owner extends Component {\n      render() {\n        return (\n          <Indirection>\n            <Context.Consumer>\n              {\n                (value) => {\n                  return (\n                    <div>\n                      <span>{value}</span>\n                      <span>{this.props.value}</span>\n                    </div>\n                  );\n                }\n              }\n            </Context.Consumer>\n          </Indirection>\n        );\n      }\n    }\n\n    function App(props) {\n      return (\n        <Context.Provider value={props.value}>\n          <Owner value={props.value} />\n        </Context.Provider>\n      );\n    }\n\n    render(<App value={2} />, container);\n    expect(container.childNodes[0].childNodes[0].childNodes[0].data).toEqual('2');\n    expect(container.childNodes[0].childNodes[1].childNodes[0].data).toEqual('2');\n\n    // Update\n    render(<App value={3} />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].childNodes[0].data).toEqual('3');\n    expect(container.childNodes[0].childNodes[1].childNodes[0].data).toEqual('3');\n  });\n\n  it('Consumer should render only once when Context value change', () => {\n    const container = createNodeElement('div');\n    const Context = createContext(1);\n    class Indirection extends Component {\n      shouldComponentUpdate() {\n        return false;\n      }\n      render() {\n        return this.props.children;\n      }\n    }\n    let consumerCount = 0;\n    let consumerWithIndirectionCount = 0;\n\n    class App extends Component {\n      render() {\n        return (\n          <Context.Provider value={this.props.value}>\n            <Context.Consumer>\n              {() => (consumerCount++, <div />)}\n            </Context.Consumer>\n            <Indirection>\n              <Context.Consumer>\n                {() => (consumerWithIndirectionCount++, <div />)}\n              </Context.Consumer>\n            </Indirection>\n          </Context.Provider>\n        );\n      }\n    }\n    render(<App value={2} />, container);\n    jest.runAllTimers();\n    consumerCount = consumerWithIndirectionCount = 0;\n\n    render(<App value={3} />, container);\n    jest.runAllTimers();\n\n    expect(consumerCount).toEqual(1);\n    expect(consumerWithIndirectionCount).toEqual(1);\n  });\n\n  it('Consumer child should be rendered in the right order', () => {\n    const container = createNodeElement('div');\n    const Context = createContext(1);\n    let Yield = [];\n    class Parent extends Component {\n      render() {\n        Yield.push('Parent');\n        return this.props.children;\n      }\n    }\n    class App extends Component {\n      render() {\n        Yield.push('App');\n        return (\n          <Context.Provider value={this.props.value}>\n            <Parent>\n              <Context.Consumer>\n                {\n                  (value) => {\n                    Yield.push('Consumer render');\n                    return <span>{value}</span>;\n                  }\n                }\n              </Context.Consumer>\n            </Parent>\n          </Context.Provider>\n        );\n      }\n    }\n    render(<App />, container);\n    Yield.length = 0;\n    render(<App value={2} />, container);\n    expect(Yield).toEqual([\n      'App',\n      'Parent',\n      'Consumer render',\n    ]);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('2');\n  });\n\n  it('provider bails out if children and value are unchanged (like sCU)', () => {\n    const container = createNodeElement('div');\n    const Context = createContext(0);\n    let logs = [];\n\n    function Child() {\n      logs.push('Child');\n      return <span>Child</span>;\n    }\n\n    const children = <Child />;\n\n    function App(props) {\n      logs.push('App');\n      return (\n        <Context.Provider value={props.value}>{children}</Context.Provider>\n      );\n    }\n\n    // Initial mount\n    render(<App value={1} />, container);\n    expect(logs).toEqual(['App', 'Child']);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('Child');\n\n    // Update\n    logs = [];\n    render(<App value={1} />, container);\n    expect(logs).toEqual(['App'\n    // Child does not re-render\n    ]);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('Child');\n  });\n\n  it('provider does not bail out if legacy context changed above', () => {\n    const container = createNodeElement('div');\n    const Context = createContext(0);\n    let logs = [];\n\n    function Child() {\n      logs.push('Child');\n      return <span>Child</span>;\n    }\n\n    const children = <Child />;\n\n    const legacyProviderRef = createRef();\n    const appRef = createRef();\n\n    class LegacyProvider extends Component {\n      static childContextTypes = {\n        legacyValue: () => {},\n      };\n      state = {legacyValue: 1};\n      getChildContext() {\n        return {legacyValue: this.state.legacyValue};\n      }\n      render() {\n        legacyProviderRef.current = this;\n        logs.push('LegacyProvider');\n        return this.props.children;\n      }\n    }\n\n    class App extends Component {\n      state = {value: 1};\n      render() {\n        appRef.current = this;\n        logs.push('App');\n        return (\n          <Context.Provider value={this.state.value}>\n            {this.props.children}\n          </Context.Provider>\n        );\n      }\n    }\n\n    // Initial mount\n    render(\n      <LegacyProvider>\n        <App value={1}>\n          {children}\n        </App>\n      </LegacyProvider>, container,\n    );\n    expect(logs).toEqual(['LegacyProvider', 'App', 'Child']);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('Child');\n\n    // Update App with same value (should bail out)\n    logs = [];\n    appRef.current.setState({value: 1});\n    jest.runAllTimers();\n    expect(logs).toEqual(['App']);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('Child');\n\n    // Update LegacyProvider (should not bail out)\n    logs = [];\n    legacyProviderRef.current.setState({value: 1});\n    jest.runAllTimers();\n    expect(logs).toEqual(['LegacyProvider', 'App', 'Child']);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('Child');\n\n    // Update App with same value (should bail out)\n    logs = [];\n    appRef.current.setState({value: 1});\n    jest.runAllTimers();\n    expect(logs).toEqual(['App']);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('Child');\n  });\n\n  it('should only update consumer when context change', () => {\n    const container = createNodeElement('div');\n    const Context = createContext('theme-default');\n    let logs = [];\n\n    class ThemeProvider extends Component {\n      state = {\n        theme: 'theme1'\n      }\n      render() {\n        logs.push('ThemeProvider');\n        return <Context.Provider value={this.state.theme}>{this.props.children}</Context.Provider>;\n      }\n    }\n\n    function ThemeDisplay(props) {\n      logs.push('ThemeDisplay');\n      return <span>{props.theme}</span>;\n    }\n\n    function ThemeConsumer() {\n      return <Context.Consumer>\n        {\n          theme => <ThemeDisplay theme={theme} />\n        }\n      </Context.Consumer>;\n    }\n\n    function OtherChild() {\n      logs.push('OtherChild');\n      return <span>OtherChild</span>;\n    }\n\n    function App() {\n      logs.push('App');\n      return [<OtherChild key={'other'} />, <ThemeConsumer key={'theme'} />];\n    }\n\n    const themeProvider = render(<ThemeProvider><App /></ThemeProvider>, container);\n    expect(logs).toEqual(['ThemeProvider', 'App', 'OtherChild', 'ThemeDisplay']);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('OtherChild');\n    expect(container.childNodes[1].childNodes[0].data).toEqual('theme1');\n\n    logs = [];\n    themeProvider.setState({\n      theme: 'theme2'\n    });\n    jest.runAllTimers();\n    expect(logs).toEqual(['ThemeProvider', 'ThemeDisplay']);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('OtherChild');\n    expect(container.childNodes[1].childNodes[0].data).toEqual('theme2');\n  });\n\n  it('render multiple Provider in different branches', () => {\n    const container = createNodeElement('div');\n    const Context = createContext(1);\n\n    function Provider(props) {\n      return (\n        <Context.Consumer>\n          {contextValue => (\n            // Multiply previous context value by 2, unless prop overrides\n            <Context.Provider value={props.value || contextValue * 2}>\n              {props.children}\n            </Context.Provider>\n          )}\n        </Context.Consumer>\n      );\n    }\n\n    function Consumer(props) {\n      return (\n        <Context.Consumer>\n          {value => <span>{value}</span>}\n        </Context.Consumer>\n      );\n    }\n\n    function App(props) {\n      return (\n        <Provider value={props.value}>\n          <Provider>\n            <Consumer />\n          </Provider>\n          <Consumer />\n          <Provider>\n            <Provider>\n              <Consumer />\n            </Provider>\n          </Provider>\n        </Provider>\n      );\n    }\n\n    render(<App value={2} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('4');\n    expect(container.childNodes[1].childNodes[0].data).toEqual('2');\n    expect(container.childNodes[2].childNodes[0].data).toEqual('8');\n\n    // Update\n    render(<App value={3} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('6');\n    expect(container.childNodes[1].childNodes[0].data).toEqual('3');\n    expect(container.childNodes[2].childNodes[0].data).toEqual('12');\n\n    // Another update\n    render(<App value={4} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('8');\n    expect(container.childNodes[1].childNodes[0].data).toEqual('4');\n    expect(container.childNodes[2].childNodes[0].data).toEqual('16');\n  });\n\n  it('render Consumer of dynamic addition', () => {\n    const container = createNodeElement('div');\n    const Context = createContext(1);\n\n    function Provider(props) {\n      return (\n        <Context.Consumer>\n          {contextValue => (\n            // Multiply previous context value by 2, unless prop overrides\n            <Context.Provider value={props.value || contextValue * 2}>\n              {props.children}\n            </Context.Provider>\n          )}\n        </Context.Consumer>\n      );\n    }\n\n    function Consumer(props) {\n      return (\n        <Context.Consumer>\n          {value => <span>{value}</span>}\n        </Context.Consumer>\n      );\n    }\n\n    let setConsumer;\n\n    function DynamicConsumer(props) {\n      const [value, setValue] = useState(false);\n      setConsumer = setValue;\n      if (value === false) return <span>0</span>;\n      return <Consumer />;\n    }\n\n    function App(props) {\n      return (\n        <Provider value={props.value}>\n          <Consumer />\n          <Provider>\n            <DynamicConsumer />\n          </Provider>\n        </Provider>\n      );\n    }\n\n    render(<App value={2} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('2');\n    expect(container.childNodes[1].childNodes[0].data).toEqual('0');\n\n    // Update\n    setConsumer(true);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toEqual('2');\n    expect(container.childNodes[1].childNodes[0].data).toEqual('4');\n  });\n\n  it('render two Consumer and one use default context value', function() {\n    const container = createNodeElement('div');\n    const ThemeContext = createContext('light');\n\n    function MyContext() {\n      return (\n        <ThemeContext.Provider value={'dark'}>\n          <MyComponent />\n        </ThemeContext.Provider>\n      );\n    };\n\n    function MyComponent() {\n      return (\n        <ThemeContext.Consumer>\n          {value => <div>{value}</div>}\n        </ThemeContext.Consumer>\n      );\n    };\n\n    function MyContext2() {\n      return (\n        <ThemeContext.Consumer>\n          {value => <div>{value}</div>}\n        </ThemeContext.Consumer>\n      );\n    }\n\n    function App() {\n      return (\n        [\n          <MyContext key={'1'} />,\n          <MyContext2 key={'2'} />\n        ]\n      );\n    };\n\n    render(<App />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('dark');\n    expect(container.childNodes[1].childNodes[0].data).toEqual('light');\n  });\n\n  it('render one Consumer use default context value', function() {\n    const container = createNodeElement('div');\n    const ThemeContext = createContext('light');\n\n    function MyContext() {\n      return (\n        <ThemeContext.Provider value={'dark'} />\n      );\n    };\n\n    function MyContext2() {\n      return (\n        <ThemeContext.Consumer>\n          {value => <div>{value}</div>}\n        </ThemeContext.Consumer>\n      );\n    }\n\n    function App() {\n      return (\n        [\n          <MyContext key={'1'} />,\n          <MyContext2 key={'2'} />\n        ]\n      );\n    };\n\n    render(<App />, container);\n    expect(container.childNodes[1].childNodes[0].data).toEqual('light');\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/__tests__/createElement.js",
    "content": "/* @jsx createElement */\n\nimport createElement from '../createElement';\nimport Host from '../vdom/host';\nimport render from '../render';\nimport ServerDriver from 'driver-server';\nimport Component from '../vdom/component';\n\ndescribe('Element', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  function renderToDocument(element) {\n    let container = createNodeElement('div');\n    render(element, container);\n    jest.runAllTimers();\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('createElement', () => {\n    function Foo(props) {\n      return <props.tag />;\n    }\n    let foo = <Foo tag=\"Foo\" />;\n    expect(foo.props.tag).toBe('Foo');\n  });\n\n  it('throws when passing null, undefined', function() {\n    expect(function() {\n      createElement(null);\n    }).toThrow();\n\n    expect(function() {\n      createElement(undefined);\n    }).toThrow();\n\n    jest.useFakeTimers();\n\n    expect(function() {\n      class ParentComp {\n        render() {\n          return createElement(null);\n        }\n      }\n\n      var component = render(<ParentComp />);\n\n      jest.runAllTimers();\n    }).toThrowError(/Invalid element type/);\n\n    jest.useRealTimers();\n  });\n\n  it('warns for keys for arrays of elements in children position', () => {\n    expect(() => renderToDocument(\n      <div>{[<div />, <div />]}</div>\n    )).toWarnDev('Each child in a list should have a unique \"key\" prop.', {withoutStack: true});\n  });\n\n  it('warns of keys for arrays of elements with owner info', () => {\n    class InnerComponent extends Component {\n      render() {\n        return this.props.childSet;\n      }\n    }\n\n    class ComponentWrapper extends Component {\n      render() {\n        return <InnerComponent childSet={[<div />, <div />]} />;\n      }\n    }\n\n    expect(() => renderToDocument(<ComponentWrapper />)).toWarnDev(\n      'Each child in a list should have a unique \"key\" prop. Check the render method of <InnerComponent>. It was passed a child from <ComponentWrapper>.',\n      {withoutStack: true}\n    );\n  });\n\n  it('does not warn for arrays of elements with keys', () => {\n    renderToDocument((\n      <div>\n        {[\n          <span key={'#1'}>1</span>,\n          <span key={'#2'}>2</span>\n        ]}\n      </div>\n    ));\n  });\n\n  it('does not warn when element is directly as children', () => {\n    renderToDocument((\n      <div>\n        <span>1</span>\n        <span>2</span>\n        <span>3</span>\n      </div>\n    ));\n  });\n\n  it('throws for the child array contains invalid element type', () => {\n    expect(() => {\n      let container = createNodeElement('div');\n      render(<div>{[{}]}</div>, container);\n      jest.runAllTimers();\n    }).toThrowError(\n      'Invalid child type, expected types: Element instance, string, boolean, array, null, undefined. (found: object with keys {})'\n    );\n\n    expect(() => {\n      let container = createNodeElement('div');\n      render(<div>{[{foo: 1}]}</div>, container);\n      jest.runAllTimers();\n    }).toThrowError(\n      'Invalid child type, expected types: Element instance, string, boolean, array, null, undefined. (found: object with keys {foo})'\n    );\n  });\n\n  it('warns for fragments of multiple elements with same key', () => {\n    expect(() => renderToDocument((\n      <div>\n        <span key={'#1'}>1</span>\n        <span key={'#1'}>2</span>\n        <span key={'#2'}>3</span>\n      </div>\n    ))).toWarnDev('Warning: Encountered two children with the same key \"#1\".', {withoutStack: true});\n  });\n\n  it('throw errors in dev mode when modify props', () => {\n    let container = createNodeElement('div');\n    function Foo(props) {\n      props.foo = 'bar';\n      return null;\n    }\n\n    expect(() => {\n      render(<Foo foo=\"foo\" />, container);\n      jest.runAllTimers();\n    }).toThrowError(/Cannot assign to read only property/);\n  });\n\n  it('make children output correct when components use the same props object', () => {\n    let thisProps = {};\n    let tagA = <div {...thisProps}>A</div>;\n    let tagB = <div {...thisProps} a={1}>B</div>;\n    let tagC = <div {...thisProps}>C</div>;\n    expect(tagA.props.children).toBe('A');\n    expect(tagB.props.children).toBe('B');\n    expect(tagC.props.children).toBe('C');\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/__tests__/forwardRef.js",
    "content": "/* @jsx createElement */\n\nimport createElement from '../createElement';\nimport Host from '../vdom/host';\nimport render from '../render';\nimport ServerDriver from 'driver-server';\nimport forwardRef from '../forwardRef';\nimport createRef from '../createRef';\nimport memo from '../memo';\n\ndescribe('forwardRef', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n  });\n\n  it('should update refs when switching between children', () => {\n    const container = createNodeElement('div');\n\n    function FunctionComponent({forwardedRef, setRefOnDiv}) {\n      return (\n        <section>\n          <div ref={setRefOnDiv ? forwardedRef : null}>First</div>\n          <span ref={setRefOnDiv ? null : forwardedRef}>Second</span>\n        </section>\n      );\n    }\n\n    const RefForwardingComponent = forwardRef((props, ref) => (\n      <FunctionComponent {...props} forwardedRef={ref} />\n    ));\n\n    const ref = createRef();\n\n    render(<RefForwardingComponent ref={ref} setRefOnDiv={true} />, container);\n    expect(ref.current.tagName).toBe('DIV');\n\n    render(<RefForwardingComponent ref={ref} setRefOnDiv={false} />, container);\n    expect(ref.current.tagName).toBe('SPAN');\n  });\n\n  it('should support rendering null', () => {\n    const container = createNodeElement('div');\n\n    const RefForwardingComponent = forwardRef((props, ref) => null);\n\n    const ref = createRef();\n\n    render(<RefForwardingComponent ref={ref} />, container);\n\n    expect(ref.current).toBe(null);\n  });\n\n  it('should support rendering null for multiple children', () => {\n    const container = createNodeElement('div');\n\n    const RefForwardingComponent = forwardRef((props, ref) => null);\n\n    const ref = createRef();\n\n    render(\n      <div>\n        <div />\n        <RefForwardingComponent ref={ref} />\n        <div />\n      </div>,\n      container\n    );\n\n    expect(ref.current).toBe(null);\n  });\n\n  it('should support defaultProps', () => {\n    const container = createNodeElement('div');\n\n    function FunctionComponent({forwardedRef, optional, required}) {\n      return (\n        <div ref={forwardedRef}>\n          <span>{optional}</span>\n          <span>{required}</span>\n        </div>\n      );\n    }\n\n    const RefForwardingComponent = forwardRef(function NamedFunction(props, ref) {\n      return <FunctionComponent {...props} forwardedRef={ref} />;\n    });\n\n\n    RefForwardingComponent.defaultProps = {\n      optional: 'default',\n    };\n\n    const ref = createRef();\n\n    render(<RefForwardingComponent ref={ref} optional=\"foo\" required=\"bar\" />, container);\n\n    expect(ref.current.childNodes[0].childNodes[0].data).toEqual('foo');\n    expect(ref.current.childNodes[1].childNodes[0].data).toEqual('bar');\n\n    render(<RefForwardingComponent ref={ref} required=\"foo\" />, container);\n\n    expect(ref.current.childNodes[0].childNodes[0].data).toEqual('default');\n    expect(ref.current.childNodes[1].childNodes[0].data).toEqual('foo');\n  });\n\n  it('should bailout if forwardRef is wrapped in memo', () => {\n    const container = createNodeElement('div');\n\n    const Component = props => <div ref={props.forwardedRef} />;\n\n    let renderCount = 0;\n\n    const RefForwardingComponent = memo(\n      forwardRef((props, ref) => {\n        renderCount++;\n        return <Component {...props} forwardedRef={ref} />;\n      }),\n    );\n\n    const ref = createRef();\n\n    render(<RefForwardingComponent ref={ref} optional=\"foo\" />, container);\n    expect(renderCount).toBe(1);\n    expect(ref.current.tagName).toBe('DIV');\n\n    render(<RefForwardingComponent ref={ref} optional=\"foo\" />, container);\n    expect(renderCount).toBe(1);\n\n    const differentRef = createRef();\n\n    render(<RefForwardingComponent ref={differentRef} optional=\"foo\" />, container);\n    expect(renderCount).toBe(2);\n    expect(ref.current).toBe(null);\n    expect(differentRef.current.tagName).toBe('DIV');\n\n    render(<RefForwardingComponent ref={ref} optional=\"bar\" />, container);\n    expect(renderCount).toBe(3);\n  });\n\n  it('should custom memo comparisons to compose', () => {\n    const container = createNodeElement('div');\n\n    const Component = props => <div ref={props.forwardedRef} />;\n\n    let renderCount = 0;\n\n    const RefForwardingComponent = memo(\n      forwardRef((props, ref) => {\n        renderCount++;\n        return <Component {...props} forwardedRef={ref} />;\n      }),\n      (o, p) => o.a === p.a && o.b === p.b,\n    );\n\n    const ref = createRef();\n\n    render(<RefForwardingComponent ref={ref} a=\"0\" b=\"0\" c=\"1\" />, container);\n    expect(renderCount).toBe(1);\n\n    expect(ref.current.tagName).toBe('DIV');\n\n    // Changing either a or b rerenders\n    render(<RefForwardingComponent ref={ref} a=\"0\" b=\"1\" c=\"1\" />, container);\n    expect(renderCount).toBe(2);\n\n    // Changing c doesn't rerender\n    render(<RefForwardingComponent ref={ref} a=\"0\" b=\"1\" c=\"2\" />, container);\n    expect(renderCount).toBe(2);\n\n    const ComposedMemo = memo(\n      RefForwardingComponent,\n      (o, p) => o.a === p.a && o.c === p.c,\n    );\n\n    render(<ComposedMemo ref={ref} a=\"0\" b=\"0\" c=\"0\" />, container);\n    expect(renderCount).toBe(3);\n\n    // Changing just b no longer updates\n    render(<ComposedMemo ref={ref} a=\"0\" b=\"1\" c=\"0\" />, container);\n    expect(renderCount).toBe(3);\n\n    // Changing just a and c updates\n    render(<ComposedMemo ref={ref} a=\"2\" b=\"2\" c=\"2\" />, container);\n    expect(renderCount).toBe(4);\n\n    // Changing just c does not update\n    render(<ComposedMemo ref={ref} a=\"2\" b=\"2\" c=\"3\" />, container);\n    expect(renderCount).toBe(4);\n\n    // Changing ref still rerenders\n    const differentRef = createRef();\n\n    render(<ComposedMemo ref={differentRef} a=\"2\" b=\"2\" c=\"3\" />, container);\n    expect(renderCount).toBe(5);\n\n    expect(ref.current).toBe(null);\n    expect(differentRef.current.tagName).toBe('DIV');\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/__tests__/fragment.js",
    "content": "/* @jsx createElement */\n\nimport createElement from '../createElement';\nimport Host from '../vdom/host';\nimport render from '../render';\nimport ServerDriver from 'driver-server';\nimport Fragment from '../fragment';\nimport Component from '../vdom/component';\n\ndescribe('Fragment', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n  });\n\n  it('render a fragment with one child', () => {\n    const container = createNodeElement('div');\n    render(\n      <Fragment>\n        <div>text</div>\n      </Fragment>,\n      container\n    );\n    expect(container.childNodes[0].tagName).toBe('DIV');\n  });\n\n  it('render a fragment with several children', () => {\n    const container = createNodeElement('div');\n    let Header = props => {\n      return <p>text</p>;\n    };\n    let Footer = props => {\n      return (\n        <Fragment>\n          <h2>text</h2>\n          <h3>text</h3>\n        </Fragment>\n      );\n    };\n\n    render(\n      <Fragment>\n        <div>text</div>\n        <span>text</span>\n        <Header />\n        <Footer />\n      </Fragment>,\n      container\n    );\n\n    expect(container.childNodes[0].tagName).toBe('DIV');\n    expect(container.childNodes[1].tagName).toBe('SPAN');\n    expect(container.childNodes[2].tagName).toBe('P');\n    expect(container.childNodes[3].tagName).toBe('H2');\n    expect(container.childNodes[4].tagName).toBe('H3');\n  });\n\n  it('render a nested fragment', () => {\n    const container = createNodeElement('div');\n    render(\n      <Fragment>\n        <Fragment>\n          <div>text</div>\n        </Fragment>\n        <span>text</span>\n        <Fragment>\n          <Fragment>\n            <Fragment>\n              {null}\n              <p />\n            </Fragment>\n            {false}\n          </Fragment>\n        </Fragment>\n      </Fragment>,\n      container\n    );\n\n    expect(container.childNodes[0].tagName).toBe('DIV');\n    expect(container.childNodes[1].tagName).toBe('SPAN');\n    expect(container.childNodes[2].nodeType).toBe(8);\n    expect(container.childNodes[3].tagName).toBe('P');\n    expect(container.childNodes[4].nodeType).toBe(8);\n  });\n\n  it('render an empty fragment', () => {\n    const container = createNodeElement('div');\n    render(<Fragment />, container);\n    expect(container.childNodes[0].nodeType).toBe(8);\n  });\n\n  it('should render correct from no empty array to empty', function() {\n    let el = createNodeElement('div');\n\n    function F({ type }) {\n      if (type === 'empty') {\n        return [];\n      }\n      return <div>2</div>;\n    }\n\n    function G({ type }) {\n      if (type === 'empty') {\n        return ['1', '2'];\n      }\n      return [];\n    }\n\n    class App extends Component {\n      render() {\n        return (\n          [\n            <div>1</div>,\n            <G type={this.props.type} />,\n            <F type={this.props.type} />,\n            <div>3</div>,\n          ]\n        );\n      }\n    }\n\n    expect(() => {\n      render(<App type=\"empty\" />, el);\n      expect(el.childNodes[0].childNodes[0].data).toBe('1');\n      expect(el.childNodes[1].data).toBe('1');\n      expect(el.childNodes[2].data).toBe('2');\n      expect(el.childNodes[3].childNodes[0].data).toBe('3');\n      render(<App />, el);\n      expect(el.childNodes[0].childNodes[0].data).toBe('1');\n      expect(el.childNodes[1].childNodes[0].data).toBe('2');\n      expect(el.childNodes[2].childNodes[0].data).toBe('3');\n    }).toWarnDev('Warning: Each child in a list should have a unique \"key\" prop. Check the render method of <App>', {withoutStack: true});\n  });\n\n  it('should render correct when swap element position', function() {\n    let el = createNodeElement('div');\n\n    function F({ type }) {\n      if (type === 'empty') {\n        return [];\n      }\n      return <span>2</span>;\n    }\n\n    function G({ type }) {\n      if (type === 'empty') {\n        return ['1', '2'];\n      }\n      return [];\n    }\n\n    class App extends Component {\n      render() {\n        if (this.props.type === 'empty') {\n          return [\n            <F />,\n            <G />,\n            <div>1</div>\n          ];\n        }\n\n        return (\n          [\n            <div>1</div>,\n            <G type={this.props.type} />,\n            <F type={this.props.type} />,\n            <div>3</div>,\n          ]\n        );\n      }\n    }\n\n    render([<div>0</div>, <App />, <App type={'empty'} />, <span>10</span>], el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('0');\n    expect(el.childNodes[1].childNodes[0].data).toBe('1');\n    expect(el.childNodes[2].childNodes[0].data).toBe('2');\n    expect(el.childNodes[3].childNodes[0].data).toBe('3');\n    expect(el.childNodes[4].childNodes[0].data).toBe('2');\n    expect(el.childNodes[5].childNodes[0].data).toBe('1');\n\n    render([<App />, <div>0</div>, <App type={'empty'} />], el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[1].childNodes[0].data).toBe('2');\n    expect(el.childNodes[2].childNodes[0].data).toBe('3');\n    expect(el.childNodes[3].childNodes[0].data).toBe('0');\n    expect(el.childNodes[4].childNodes[0].data).toBe('2');\n    expect(el.childNodes[5].childNodes[0].data).toBe('1');\n    expect(el.childNodes[6]).toBe(undefined);\n  });\n\n  it('should render correct from empty array to other', function() {\n    let el = createNodeElement('div');\n\n    function F({ type }) {\n      if (type === 'empty') {\n        return [];\n      }\n      return <div>2</div>;\n    }\n\n    class App extends Component {\n      render() {\n        return (\n          [\n            <div>1</div>,\n            <F type={this.props.type} />,\n            <div>3</div>,\n          ]\n        );\n      }\n    }\n\n    render(<App type=\"empty\" />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[1].childNodes[0].data).toBe('3');\n    render(<App />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[1].childNodes[0].data).toBe('2');\n    expect(el.childNodes[2].childNodes[0].data).toBe('3');\n  });\n\n  it('should render correct from mixed array to another mixed array', function() {\n    let el = createNodeElement('div');\n\n    function App(props) {\n      if (props.type === 'empty') {\n        return [\n          [<div>1</div>, <div>2</div>],\n          [\n            <div>3</div>,\n            <div>4</div>,\n            [<div>5</div>]\n          ]\n        ];\n      }\n\n      return [\n        [<div>1</div>],\n        [<div>2</div>, <div>3</div>],\n        <div>4</div>,\n        [[[<div>5</div>]]]\n      ];\n    }\n\n    render(<App type={'empty'} />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[1].childNodes[0].data).toBe('2');\n    expect(el.childNodes[2].childNodes[0].data).toBe('3');\n    expect(el.childNodes[3].childNodes[0].data).toBe('4');\n    expect(el.childNodes[4].childNodes[0].data).toBe('5');\n\n    render(<App />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[1].childNodes[0].data).toBe('2');\n    expect(el.childNodes[2].childNodes[0].data).toBe('3');\n    expect(el.childNodes[3].childNodes[0].data).toBe('4');\n    expect(el.childNodes[4].childNodes[0].data).toBe('5');\n  });\n\n  it('should render correct when first element is replaced', function() {\n    let el = createNodeElement('div');\n\n    function App(props) {\n      if (props.type === 'empty') {\n        return [\n          [<div>111</div>],\n          <div>0</div>\n        ];\n      }\n\n      return [<span>2</span>, <div>0</div>];\n    }\n\n    render(<App />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('2');\n    expect(el.childNodes[1].childNodes[0].data).toBe('0');\n\n    render(<App type={'empty'} />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('111');\n    expect(el.childNodes[1].childNodes[0].data).toBe('0');\n  });\n\n  it('fragment should diff correct when fist element is empty array', function() {\n    let el = createNodeElement('div');\n\n    function App(props) {\n      if (props.type === 'empty') {\n        return [\n          [[], [], []],\n          [],\n          [],\n          <span>0</span>,\n          <span>1</span>\n        ];\n      } else {\n        return [\n          <div>2</div>,\n          <span>0</span>,\n          <span>1</span>\n        ];\n      }\n    }\n\n    render(<App type=\"empty\" />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('0');\n    expect(el.childNodes[1].childNodes[0].data).toBe('1');\n\n    render(<App />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('2');\n    expect(el.childNodes[1].childNodes[0].data).toBe('0');\n    expect(el.childNodes[2].childNodes[0].data).toBe('1');\n  });\n\n  it('should render correct when embedded in fragment', function() {\n    let el = createNodeElement('div');\n\n    function App(props) {\n      if (props.type === 'empty') {\n        return [\n          [[], [], []],\n          [],\n          [],\n          <span>1</span>,\n          <span>2</span>\n        ];\n      } else {\n        return [\n          <div>5</div>,\n          <span>1</span>,\n          <span>2</span>\n        ];\n      }\n    }\n\n    render([<span>0</span>, <App type=\"empty\" />, <span>3</span>], el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('0');\n    expect(el.childNodes[1].childNodes[0].data).toBe('1');\n    expect(el.childNodes[2].childNodes[0].data).toBe('2');\n    expect(el.childNodes[3].childNodes[0].data).toBe('3');\n\n    render([<span>0</span>, <App />, <span>4</span>], el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('0');\n    expect(el.childNodes[1].childNodes[0].data).toBe('5');\n    expect(el.childNodes[2].childNodes[0].data).toBe('1');\n    expect(el.childNodes[3].childNodes[0].data).toBe('2');\n    expect(el.childNodes[4].childNodes[0].data).toBe('4');\n  });\n\n  it('from empty array to not-empty', function() {\n    let el = createNodeElement('div');\n\n    function App(props) {\n      if (props.type === 'empty') {\n        return [\n          <span>0</span>,\n          [],\n          <span>3</span>,\n        ];\n      } else {\n        return [\n          <span>0</span>,\n          [\n            <span>1</span>,\n            <span>2</span>,\n          ],\n          <span>3</span>\n        ];\n      }\n    }\n\n    render(<App type=\"empty\" />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('0');\n    expect(el.childNodes[1].childNodes[0].data).toBe('3');\n\n    render(<App />, el);\n\n    expect(el.childNodes[0].childNodes[0].data).toBe('0');\n    expect(el.childNodes[1].childNodes[0].data).toBe('1');\n    expect(el.childNodes[2].childNodes[0].data).toBe('2');\n    expect(el.childNodes[3].childNodes[0].data).toBe('3');\n  });\n\n  it('previous node is unmount', function() {\n    let el = createNodeElement('div');\n\n    function App(props) {\n      if (props.type === 'empty') {\n        return [\n          <span>0</span>,\n          <span>1</span>,\n          [[]],\n          <span>2</span>,\n        ];\n      } else {\n        return [\n          [],\n          [],\n          [\n            <span>1</span>,\n            <span>2</span>,\n          ],\n          <span>3</span>\n        ];\n      }\n    }\n\n    render(<App type=\"empty\" />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('0');\n    expect(el.childNodes[1].childNodes[0].data).toBe('1');\n    expect(el.childNodes[2].childNodes[0].data).toBe('2');\n\n    render(<App />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[1].childNodes[0].data).toBe('2');\n    expect(el.childNodes[2].childNodes[0].data).toBe('3');\n  });\n\n  it('should render correct from not empty array to other', function() {\n    let el = createNodeElement('div');\n\n    function F({ type }) {\n      if (type === 'notEmpty') {\n        return ['4'];\n      }\n      return <div>2</div>;\n    }\n\n    class App extends Component {\n      render() {\n        return (\n          [\n            <div>1</div>,\n            <F type={this.props.type} />,\n            <div>3</div>,\n          ]\n        );\n      }\n    }\n\n    render(<App type={'notEmpty'} />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[1].data).toBe('4');\n    expect(el.childNodes[2].childNodes[0].data).toBe('3');\n\n    render(<App />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[1].childNodes[0].data).toBe('2');\n    expect(el.childNodes[2].childNodes[0].data).toBe('3');\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/__tests__/hooks.js",
    "content": "/* @jsx createElement */\n\nimport createElement from '../createElement';\nimport Host from '../vdom/host';\nimport render from '../render';\nimport ServerDriver from 'driver-server';\nimport createContext from '../createContext';\nimport {useState, useContext, useEffect, useLayoutEffect, useRef, useReducer, useImperativeHandle, useMemo} from '../hooks';\nimport forwardRef from '../forwardRef';\nimport createRef from '../createRef';\nimport memo from '../memo';\nimport Component from '../vdom/component';\n\ndescribe('hooks', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('works inside a function component with useState', () => {\n    const container = createNodeElement('div');\n\n    function App(props) {\n      const [value, setValue] = useState(props.value);\n\n      return (\n        <span key={value}>{value}</span>\n      );\n    }\n\n    render(<App value={2} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('2');\n  });\n\n  it('lazy state initializer', () => {\n    const container = createNodeElement('div');\n    let stateUpdater = null;\n    function Counter(props) {\n      const [count, updateCount] = useState(() => {\n        return props.initialState + 1;\n      });\n      stateUpdater = updateCount;\n      return <span>{count}</span>;\n    }\n\n    render(<Counter initialState={1} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('2');\n\n    stateUpdater(10);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toEqual('10');\n  });\n\n  it('returns the same updater function every time', () => {\n    const container = createNodeElement('div');\n    let updaters = [];\n    function Counter() {\n      const [count, updateCount] = useState(0);\n      updaters.push(updateCount);\n      return <span>{count}</span>;\n    }\n    render(<Counter />, container);\n\n    expect(container.childNodes[0].childNodes[0].data).toEqual('0');\n\n    updaters[0](1);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toEqual('1');\n\n    updaters[0](count => count + 10);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toEqual('11');\n\n    expect(updaters).toEqual([updaters[0], updaters[0], updaters[0]]);\n  });\n\n\n  it('mount and update a function component with useLayoutEffect', () => {\n    const container = createNodeElement('div');\n\n    let renderCounter = 0;\n    let effectCounter = 0;\n    let cleanupCounter = 0;\n\n    function Counter(props) {\n      useLayoutEffect(\n        () => {\n          ++effectCounter;\n          return () => {\n            ++cleanupCounter;\n          };\n        }\n      );\n      ++renderCounter;\n      return <span>{props.count}</span>;\n    }\n\n    render(<Counter count={0} />, container);\n    expect(effectCounter).toEqual(1);\n    expect(renderCounter).toEqual(1);\n    expect(cleanupCounter).toEqual(0);\n\n    render(<Counter count={1} />, container);\n    expect(renderCounter).toEqual(2);\n    expect(effectCounter).toEqual(2);\n    expect(cleanupCounter).toEqual(1);\n\n    render(<Counter count={2} />, container);\n    expect(renderCounter).toEqual(3);\n    expect(effectCounter).toEqual(3);\n    expect(cleanupCounter).toEqual(2);\n  });\n\n  it('mount and update a function component with useLayout and useLayoutEffect', () => {\n    const container = createNodeElement('div');\n\n    let logs = [];\n\n    function Counter(props) {\n      useEffect(\n        () => {\n          logs.push('create1');\n          return () => {\n            logs.push('destory1');\n          };\n        }\n      );\n\n      useLayoutEffect(\n        () => {\n          logs.push('create2');\n          return () => {\n            logs.push('destory2');\n          };\n        }\n      );\n      logs.push('render');\n      return <span>{props.count}</span>;\n    }\n\n    render(<Counter count={0} />, container);\n    jest.runAllTimers();\n    expect(logs).toEqual([\n      'render', 'create2', 'create1'\n    ]);\n\n    render(<Counter count={1} />, container);\n    jest.runAllTimers();\n    expect(logs).toEqual([\n      'render', 'create2', 'create1',\n      'render', 'destory2', 'create2', 'destory1', 'create1']);\n\n    render(<Counter count={2} />, container);\n    jest.runAllTimers();\n    expect(logs).toEqual([\n      'render', 'create2', 'create1',\n      'render', 'destory2', 'create2', 'destory1', 'create1',\n      'render', 'destory2', 'create2', 'destory1', 'create1']);\n  });\n\n  it('mount and update a function component with useEffect', () => {\n    const container = createNodeElement('div');\n\n    let renderCounter = 0;\n    let effectCounter = 0;\n    let cleanupCounter = 0;\n\n    function Counter(props) {\n      useEffect(\n        () => {\n          ++effectCounter;\n          return () => {\n            ++cleanupCounter;\n          };\n        }\n      );\n      ++renderCounter;\n      return <span>{props.count}</span>;\n    }\n\n    render(<Counter count={0} />, container);\n    jest.runAllTimers();\n    expect(effectCounter).toEqual(1);\n    expect(renderCounter).toEqual(1);\n    expect(cleanupCounter).toEqual(0);\n\n    render(<Counter count={1} />, container);\n    jest.runAllTimers();\n    expect(renderCounter).toEqual(2);\n    expect(effectCounter).toEqual(2);\n    expect(cleanupCounter).toEqual(1);\n\n    render(<Counter count={2} />, container);\n    jest.runAllTimers();\n    expect(renderCounter).toEqual(3);\n    expect(effectCounter).toEqual(3);\n    expect(cleanupCounter).toEqual(2);\n  });\n\n  it('only update if the inputs has changed with useLayoutEffect', () => {\n    const container = createNodeElement('div');\n\n    let renderCounter = 0;\n    let effectCounter = 0;\n    let cleanupCounter = 0;\n\n    function Counter(props) {\n      const [text, udpateText] = useState('foo');\n      useLayoutEffect(\n        () => {\n          ++effectCounter;\n          udpateText('bar');\n          return () => {\n            ++cleanupCounter;\n          };\n        },\n        [props.count]\n      );\n      ++renderCounter;\n      return <span>{text}</span>;\n    }\n\n    render(<Counter count={0} />, container);\n    jest.runAllTimers();\n    expect(effectCounter).toEqual(1);\n    expect(renderCounter).toEqual(2);\n    expect(cleanupCounter).toEqual(0);\n\n    render(<Counter count={0} />, container);\n    jest.runAllTimers();\n    expect(effectCounter).toEqual(1);\n    expect(renderCounter).toEqual(3);\n    expect(cleanupCounter).toEqual(0);\n\n    render(<Counter count={1} />, container);\n    jest.runAllTimers();\n    expect(effectCounter).toEqual(2);\n    expect(renderCounter).toEqual(4);\n    expect(cleanupCounter).toEqual(1);\n  });\n\n  it('only update if the inputs has changed with useEffect', () => {\n    const container = createNodeElement('div');\n\n    let renderCounter = 0;\n    let effectCounter = 0;\n    let cleanupCounter = 0;\n\n    function Counter(props) {\n      const [text, udpateText] = useState('foo');\n      useEffect(\n        () => {\n          ++effectCounter;\n          udpateText('bar');\n          return () => {\n            ++cleanupCounter;\n          };\n        },\n        [props.count]\n      );\n      ++renderCounter;\n      return <span>{text}</span>;\n    }\n\n    render(<Counter count={0} />, container);\n    jest.runAllTimers();\n    expect(effectCounter).toEqual(1);\n    expect(renderCounter).toEqual(2);\n    expect(cleanupCounter).toEqual(0);\n\n    render(<Counter count={0} />, container);\n    jest.runAllTimers();\n    expect(effectCounter).toEqual(1);\n    expect(renderCounter).toEqual(3);\n    expect(cleanupCounter).toEqual(0);\n\n    render(<Counter count={1} />, container);\n    jest.runAllTimers();\n    expect(effectCounter).toEqual(2);\n    expect(renderCounter).toEqual(4);\n    expect(cleanupCounter).toEqual(1);\n  });\n\n  it('update when the inputs has changed with useLayoutEffect', () => {\n    const container = createNodeElement('div');\n\n    let renderCounter = 0;\n    let effectCounter = 0;\n    let cleanupCounter = 0;\n\n    function Counter(props) {\n      const [count, updateCount] = useState(0);\n      useLayoutEffect(\n        () => {\n          ++effectCounter;\n          updateCount(1);\n          return () => {\n            ++cleanupCounter;\n          };\n        },\n        [count]\n      );\n      ++renderCounter;\n      return <span>{count}</span>;\n    }\n\n    render(<Counter />, container);\n    jest.runAllTimers();\n    expect(effectCounter).toEqual(2);\n    expect(renderCounter).toEqual(2);\n    expect(cleanupCounter).toEqual(1);\n  });\n\n  it('would run only on mount and clean up on unmount with useLayoutEffect', () => {\n    const container = createNodeElement('div');\n\n    let renderCounter = 0;\n    let effectCounter = 0;\n    let cleanupCounter = 0;\n\n    function Counter() {\n      const [count, updateCount] = useState(0);\n      useLayoutEffect(\n        () => {\n          ++effectCounter;\n          updateCount(count + 1);\n          return () => {\n            ++cleanupCounter;\n          };\n        },\n        []\n      );\n      ++renderCounter;\n      return <span>{count}</span>;\n    }\n\n    render(<Counter />, container);\n    jest.runAllTimers();\n    expect(effectCounter).toEqual(1);\n    expect(renderCounter).toEqual(2);\n    expect(cleanupCounter).toEqual(0);\n  });\n\n  it('works inside a function component with useContext', () => {\n    const container = createNodeElement('div');\n    const Context = createContext(1);\n\n    function Consumer(props) {\n      const value = useContext(Context);\n\n      return (\n        <span>{value}</span>\n      );\n    }\n\n    function App(props) {\n      return (\n        <Context.Provider value={props.value}>\n          <Consumer />\n        </Context.Provider>\n      );\n    }\n\n    render(<App value={2} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('2');\n\n    // Update\n    render(<App value={3} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('3');\n  });\n\n  it('should return the same ref during re-renders', () => {\n    const container = createNodeElement('div');\n    let renderCounter = 0;\n    function Counter() {\n      const ref = useRef('val');\n      const [firstRef] = useState(ref);\n\n      if (firstRef !== ref) {\n        throw new Error('should never change');\n      }\n      renderCounter++;\n      return <span>{ref.current}</span>;\n    }\n\n    render(<Counter />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('val');\n    expect(renderCounter).toEqual(1);\n\n    render(<Counter foo=\"bar\" />, container);\n    expect(renderCounter).toEqual(2);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('val');\n  });\n\n  it('bails out in the render phase if all of the state is the same', () => {\n    const container = createNodeElement('div');\n    const logs = [];\n\n    logs.flush = function() {\n      const result = [...logs];\n      logs.length = 0;\n      return result;\n    };\n\n    function Child({text}) {\n      logs.push('Child: ' + text);\n      return text;\n    }\n\n    let setCounter1;\n    let setCounter2;\n    function Parent() {\n      const [counter1, _setCounter1] = useState(0);\n      setCounter1 = _setCounter1;\n      const [counter2, _setCounter2] = useState(0);\n      setCounter2 = _setCounter2;\n\n      const text = `${counter1}, ${counter2}`;\n      logs.push(`Parent: ${text}`);\n      useLayoutEffect(() => {\n        logs.push(`Effect: ${text}`);\n      });\n\n      return <Child text={text} />;\n    }\n\n    const root = render(<Parent />, container);\n    expect(logs.flush()).toEqual([\n      'Parent: 0, 0',\n      'Child: 0, 0',\n      'Effect: 0, 0',\n    ]);\n    expect(container.childNodes[0].data).toEqual('0, 0');\n\n    // Normal update\n    setCounter1(1);\n    setCounter2(1);\n    jest.runAllTimers();\n\n    expect(logs.flush()).toEqual([\n      'Parent: 1, 1',\n      'Child: 1, 1',\n      'Effect: 1, 1',\n    ]);\n\n    // This time, one of the state updates but the other one doesn't. So we\n    // can't bail out.\n\n    setCounter1(1);\n    setCounter2(2);\n    jest.runAllTimers();\n\n    expect(logs.flush()).toEqual([\n      'Parent: 1, 2',\n      'Child: 1, 2',\n      'Effect: 1, 2',\n    ]);\n\n    // Lots of updates that eventually resolve to the current values.\n\n    setCounter1(9);\n    setCounter2(3);\n    setCounter1(4);\n    setCounter2(7);\n    setCounter1(1);\n    setCounter2(2);\n    jest.runAllTimers();\n\n    // Because the final values are the same as the current values, the\n    // component bails out.\n    expect(logs.flush()).toEqual(['Parent: 1, 2', 'Effect: 1, 2']);\n\n    // prepare to check SameValue\n\n    setCounter1(0 / -1);\n    setCounter2(NaN);\n    jest.runAllTimers();\n\n    expect(logs.flush()).toEqual([\n      'Parent: 0, NaN',\n      'Child: 0, NaN',\n      'Effect: 0, NaN',\n    ]);\n\n    // check if re-setting to negative 0 / NaN still bails out\n\n    setCounter1(0 / -1);\n    setCounter2(NaN);\n    setCounter2(Infinity);\n    setCounter2(NaN);\n    jest.runAllTimers();\n\n    expect(logs.flush()).toEqual(['Parent: 0, NaN', 'Effect: 0, NaN']);\n\n    // check if changing negative 0 to positive 0 does not bail out\n\n    setCounter1(0);\n    jest.runAllTimers();\n\n    expect(logs.flush()).toEqual([\n      'Parent: 0, NaN',\n      'Child: 0, NaN',\n      'Effect: 0, NaN',\n    ]);\n  });\n\n  it('bails out in render phase if all the state is the same and props bail out with memo', () => {\n    const container = createNodeElement('div');\n    const logs = [];\n    logs.flush = function() {\n      const result = [...logs];\n      logs.length = 0;\n      return result;\n    };\n\n    function Child({text}) {\n      logs.push('Child: ' + text);\n      return text;\n    }\n\n    let setCounter1;\n    let setCounter2;\n\n    function Parent({theme}) {\n      const [counter1, _setCounter1] = useState(0);\n      setCounter1 = _setCounter1;\n      const [counter2, _setCounter2] = useState(0);\n      setCounter2 = _setCounter2;\n\n      const text = `${counter1}, ${counter2} (${theme})`;\n      logs.push(`Parent: ${text}`);\n\n      return <Child text={text} />;\n    }\n\n    Parent = memo(Parent);\n\n    render(<Parent theme=\"light\" />, container);\n    expect(logs.flush()).toEqual([\n      'Parent: 0, 0 (light)',\n      'Child: 0, 0 (light)',\n    ]);\n    expect(container.childNodes[0].data).toEqual('0, 0 (light)');\n\n\n    setCounter1(1);\n    setCounter2(1);\n    jest.runAllTimers();\n    expect(logs.flush()).toEqual([\n      'Parent: 1, 1 (light)',\n      'Child: 1, 1 (light)',\n    ]);\n\n    // This time, one of the state updates but the other one doesn't. So we\n    // can't bail out.\n\n    setCounter1(1);\n    setCounter2(2);\n    jest.runAllTimers();\n    expect(logs.flush()).toEqual([\n      'Parent: 1, 2 (light)',\n      'Child: 1, 2 (light)',\n    ]);\n\n    // Updates bail out, but component still renders because props\n    // have changed\n    setCounter1(1);\n    setCounter2(2);\n    render(<Parent theme=\"dark\" />, container);\n    jest.runAllTimers();\n    expect(logs.flush()).toEqual(['Parent: 1, 2 (dark)', 'Child: 1, 2 (dark)']);\n\n    // Both props and state bail out\n    setCounter1(1);\n    setCounter2(2);\n    render(<Parent theme=\"dark\" />, container);\n    jest.runAllTimers();\n    expect(logs.flush()).toEqual([]);\n  });\n\n  it('never bails out if context has changed', () => {\n    const container = createNodeElement('div');\n    const logs = [];\n\n    logs.flush = function() {\n      const result = [...logs];\n      logs.length = 0;\n      return result;\n    };\n\n    const ThemeContext = createContext('light');\n\n    let setTheme;\n    function ThemeProvider({children}) {\n      const [theme, _setTheme] = useState('light');\n      logs.push('Theme: ' + theme);\n      setTheme = _setTheme;\n      return (\n        <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>\n      );\n    }\n\n    function Child({text}) {\n      logs.push('Child: ' + text);\n      return text;\n    }\n\n    let setCounter;\n    function Parent() {\n      const [counter, _setCounter] = useState(0);\n      setCounter = _setCounter;\n\n      const theme = useContext(ThemeContext);\n\n      const text = `${counter} (${theme})`;\n      logs.push(`Parent: ${text}`);\n      useLayoutEffect(() => {\n        logs.push(`Effect: ${text}`);\n      });\n      return <Child text={text} />;\n    }\n\n    const root = render(\n      <ThemeProvider>\n        <Parent />\n      </ThemeProvider>\n      , container);\n\n    expect(logs.flush()).toEqual([\n      'Theme: light',\n      'Parent: 0 (light)',\n      'Child: 0 (light)',\n      'Effect: 0 (light)',\n    ]);\n    expect(container.childNodes[0].data).toEqual('0 (light)');\n\n    // Updating the theme to the same value doesn't cause the consumers\n    // to re-render.\n    setTheme('light');\n    expect(logs.flush()).toEqual([]);\n    expect(container.childNodes[0].data).toEqual('0 (light)');\n\n    // Normal update\n    setCounter(1);\n    jest.runAllTimers();\n    expect(logs.flush()).toEqual([\n      'Parent: 1 (light)',\n      'Child: 1 (light)',\n      'Effect: 1 (light)',\n    ]);\n    expect(container.childNodes[0].data).toEqual('1 (light)');\n\n    // Update that doesn't change state, but the context changes, too, so it\n    // can't bail out\n\n    setCounter(1);\n    setTheme('dark');\n    jest.runAllTimers();\n\n    expect(logs.flush()).toEqual([\n      'Theme: dark',\n      'Parent: 1 (dark)',\n      'Child: 1 (dark)',\n      'Effect: 1 (dark)',\n    ]);\n    expect(container.childNodes[0].data).toEqual('1 (dark)');\n  });\n\n  it('rerender only once when context changes', () => {\n    const container = createNodeElement('div');\n    const context = createContext(4);\n    let logs = [];\n\n    function Parent() {\n      return <context.Provider value={this.props.value}>{this.props.children}</context.Provider>;\n    }\n\n    function Child() {\n      logs.push('Child');\n      const val = useContext(context);\n      return val;\n    }\n\n    let setValue;\n    function App() {\n      const [val, setVal] = useState(1);\n      setValue = setVal;\n      return <Parent value={val}><Child /></Parent>;\n    }\n\n    render(<App />, container);\n    expect(logs).toEqual([\n      'Child'\n    ]);\n    expect(container.childNodes[0].data).toEqual('1');\n\n    logs = [];\n    setValue(2);\n    jest.runAllTimers();\n    expect(logs).toEqual([\n      'Child'\n    ]);\n    expect(container.childNodes[0].data).toEqual('2');\n  });\n\n  it('destory function of a passive effect should call synchronously', () => {\n    const container = createNodeElement('div');\n    const event = {\n      listeners: [],\n      emit: () => event.listeners.forEach(f => f()),\n      off: (f) => event.listeners = event.listeners.filter(_f => _f !== f),\n      on: (f) => event.listeners.push(f)\n    };\n\n    function useForceUpdate() {\n      const [, setCount] = useState(0);\n      return () => setCount(count => count + 1);\n    }\n\n    function Child() {\n      const forceUpdate = useForceUpdate();\n      useEffect(() => {\n        event.on(forceUpdate);\n        return () => {\n          event.off(forceUpdate);\n        };\n      });\n      return <div>child</div>;\n    }\n\n    function App(props) {\n      useLayoutEffect(() => {\n        event.emit();\n      }, [props.type]);\n      return props.type === 1 ? <Child /> : null;\n    }\n\n    render(<App type={1} />, container);\n    expect(container.childNodes[0].childNodes[0].data).toEqual('child');\n    render(<App type={2} />, container);\n    expect(container.childNodes[0].nodeType).toBe(8);\n  });\n\n  describe('updates during the render phase', () => {\n    it('restarts the render function and applies the new updates on top', () => {\n      const container = createNodeElement('div');\n      function ScrollView({row: newRow}) {\n        let [isScrollingDown, setIsScrollingDown] = useState(false);\n        let [row, setRow] = useState(null);\n\n        if (row !== newRow) {\n          // Row changed since last render. Update isScrollingDown.\n          setIsScrollingDown(row !== null && newRow > row);\n          setRow(newRow);\n        }\n\n        return <div>{`Scrolling down: ${isScrollingDown}`}</div>;\n      }\n\n      render(<ScrollView row={1} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Scrolling down: false');\n      render(<ScrollView row={5} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Scrolling down: true');\n      render(<ScrollView row={5} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Scrolling down: true');\n      render(<ScrollView row={10} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Scrolling down: true');\n      render(<ScrollView row={2} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Scrolling down: false');\n      render(<ScrollView row={2} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Scrolling down: false');\n    });\n\n    it('updates multiple times within same render function', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Counter({row: newRow}) {\n        let [count, setCount] = useState(0);\n        if (count < 12) {\n          setCount(c => c + 1);\n          setCount(c => c + 1);\n          setCount(c => c + 1);\n        }\n        logs.push('Render: ' + count);\n        return <span>{count}</span>;\n      }\n\n      render(<Counter />, container);\n      expect(logs).toEqual([\n        // Should increase by three each time\n        'Render: 0',\n        'Render: 3',\n        'Render: 6',\n        'Render: 9',\n        'Render: 12',\n      ]);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('12');\n    });\n\n    it('throws after too many iterations', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Counter({row: newRow}) {\n        let [count, setCount] = useState(0);\n        setCount(count + 1);\n        logs.push('Render: ' + count);\n        return <span>{count}</span>;\n      }\n      // render(<Counter />, container);\n      expect(() => {\n        render(<Counter />, container);\n        jest.runAllTimers();\n      }).toThrowError(\n        'Too many re-renders, the number of renders is limited to prevent an infinite loop.'\n      );\n    });\n\n    it('works with useReducer', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function reducer(state, action) {\n        return action === 'increment' ? state + 1 : state;\n      }\n      function Counter({row: newRow}) {\n        let [count, dispatch] = useReducer(reducer, 0);\n        if (count < 3) {\n          dispatch('increment');\n        }\n        logs.push('Render: ' + count);\n        return <span>{count}</span>;\n      }\n\n      render(<Counter />, container);\n      expect(logs).toEqual([\n        'Render: 0',\n        'Render: 1',\n        'Render: 2',\n        'Render: 3',\n      ]);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('3');\n    });\n\n    it('uses reducer passed at time of render, not time of dispatch', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      // This test is a bit contrived but it demonstrates a subtle edge case.\n\n      // Reducer A increments by 1. Reducer B increments by 10.\n      function reducerA(state, action) {\n        switch (action) {\n          case 'increment':\n            return state + 1;\n          case 'reset':\n            return 0;\n        }\n      }\n      function reducerB(state, action) {\n        switch (action) {\n          case 'increment':\n            return state + 10;\n          case 'reset':\n            return 0;\n        }\n      }\n      function Counter({row: newRow}, ref) {\n        let [reducer, setReducer] = useState(() => reducerA);\n        let [count, dispatch] = useReducer(reducer, 0);\n        useImperativeHandle(ref, () => ({dispatch}));\n        if (count < 20) {\n          dispatch('increment');\n          // Swap reducers each time we increment\n          if (reducer === reducerA) {\n            setReducer(() => reducerB);\n          } else {\n            setReducer(() => reducerA);\n          }\n        }\n        logs.push('Render: ' + count);\n        return <span>{count}</span>;\n      }\n      Counter = forwardRef(Counter);\n      const counter = createRef(null);\n      render(<Counter ref={counter} />, container);\n      expect(logs).toEqual([\n        // The count should increase by alternating amounts of 10 and 1\n        // until we reach 21.\n        'Render: 0',\n        'Render: 10',\n        'Render: 11',\n        'Render: 21',\n      ]);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('21');\n      logs = [];\n\n      // Test that it works on update, too. This time the log is a bit different\n      // because we started with reducerB instead of reducerA.\n      counter.current.dispatch('reset');\n      jest.runAllTimers();\n      expect(logs).toEqual([\n        'Render: 0',\n        'Render: 1',\n        'Render: 11',\n        'Render: 12',\n        'Render: 22',\n      ]);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('22');\n    });\n  });\n\n  describe('useReducer', () => {\n    it('simple mount and update', () => {\n      const container = createNodeElement('div');\n      const INCREMENT = 'INCREMENT';\n      const DECREMENT = 'DECREMENT';\n\n      function reducer(state, action) {\n        switch (action) {\n          case 'INCREMENT':\n            return state + 1;\n          case 'DECREMENT':\n            return state - 1;\n          default:\n            return state;\n        }\n      }\n\n      function Counter(props, ref) {\n        const [count, dispatch] = useReducer(reducer, 0);\n        useImperativeHandle(ref, () => ({dispatch}));\n        return <span>{count}</span>;\n      }\n      Counter = forwardRef(Counter);\n      const counter = createRef(null);\n      render(<Counter ref={counter} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('0');\n\n      counter.current.dispatch(INCREMENT);\n      jest.runAllTimers();\n      expect(container.childNodes[0].childNodes[0].data).toEqual('1');\n\n      counter.current.dispatch(DECREMENT);\n      counter.current.dispatch(DECREMENT);\n      counter.current.dispatch(DECREMENT);\n      jest.runAllTimers();\n      expect(container.childNodes[0].childNodes[0].data).toEqual('-2');\n\n      counter.current.dispatch(DECREMENT);\n      counter.current.dispatch(INCREMENT);\n      counter.current.dispatch(INCREMENT);\n      counter.current.dispatch(INCREMENT);\n      counter.current.dispatch(DECREMENT);\n      counter.current.dispatch(DECREMENT);\n      counter.current.dispatch(DECREMENT);\n      counter.current.dispatch(INCREMENT);\n      jest.runAllTimers();\n      expect(container.childNodes[0].childNodes[0].data).toEqual('-2');\n    });\n\n    it('lazy init', () => {\n      const container = createNodeElement('div');\n      const logs = [];\n\n      logs.flush = function() {\n        const result = [...logs];\n        logs.length = 0;\n        return result;\n      };\n\n      const INCREMENT = 'INCREMENT';\n      const DECREMENT = 'DECREMENT';\n\n      function reducer(state, action) {\n        switch (action) {\n          case INCREMENT:\n            return state + 1;\n          case DECREMENT:\n            return state - 1;\n          default:\n            return state;\n        }\n      }\n\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n\n      function Counter(props, ref) {\n        const [count, dispatch] = useReducer(reducer, props, p => {\n          logs.push('Init');\n          return p.initialCount;\n        });\n        useImperativeHandle(ref, () => ({dispatch}));\n        return <Text text={'Count: ' + count} />;\n      }\n      Counter = forwardRef(Counter);\n      const counter = createRef(null);\n      render(<Counter initialCount={10} ref={counter} />, container);\n      expect(logs.flush()).toEqual(['Init', 'Count: 10']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 10');\n\n      counter.current.dispatch(INCREMENT);\n      jest.runAllTimers();\n      expect(logs.flush()).toEqual(['Count: 11']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 11');\n\n      counter.current.dispatch(DECREMENT);\n      counter.current.dispatch(DECREMENT);\n      counter.current.dispatch(DECREMENT);\n      jest.runAllTimers();\n      expect(logs.flush()).toEqual(['Count: 8']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 8');\n    });\n\n    it('works with effect', () => {\n      const container = createNodeElement('div');\n      const logs = [];\n\n      logs.flush = function() {\n        const result = [...logs];\n        logs.length = 0;\n        return result;\n      };\n\n      function Child({text}) {\n        logs.push('Child: ' + text);\n        return text;\n      }\n\n      function reducer(state, action) {\n        return action;\n      }\n\n      let setCounter1;\n      let setCounter2;\n      function Parent() {\n        const [counter1, _setCounter1] = useReducer(reducer, 0);\n        setCounter1 = _setCounter1;\n        const [counter2, _setCounter2] = useReducer(reducer, 0);\n        setCounter2 = _setCounter2;\n\n        const text = `${counter1}, ${counter2}`;\n        logs.push(`Parent: ${text}`);\n        useLayoutEffect(() => {\n          logs.push(`Effect: ${text}`);\n        });\n        return <Child text={text} />;\n      }\n\n      const root = render(<Parent />, container);\n      expect(logs.flush()).toEqual([\n        'Parent: 0, 0',\n        'Child: 0, 0',\n        'Effect: 0, 0',\n      ]);\n      expect(container.childNodes[0].data).toEqual('0, 0');\n\n      // Normal update\n      setCounter1(1);\n      setCounter1(2);\n      setCounter1(2);\n      setCounter1(3);\n      setCounter2(2);\n      setCounter1(3);\n      setCounter1(3);\n      setCounter2(4);\n      jest.runAllTimers();\n\n      expect(logs.flush()).toEqual([\n        'Parent: 3, 4',\n        'Child: 3, 4',\n        'Effect: 3, 4',\n      ]);\n\n\n      setCounter1(2);\n      setCounter2(2);\n      jest.runAllTimers();\n\n      expect(logs.flush()).toEqual([\n        'Parent: 2, 2',\n        'Child: 2, 2',\n        'Effect: 2, 2',\n      ]);\n\n      setCounter1(2);\n      setCounter2(2);\n      jest.runAllTimers();\n\n      expect(logs.flush()).toEqual([]);\n    });\n  });\n\n  describe('useEffect', () => {\n    it('simple mount and update', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Counter(props) {\n        useEffect(() => {\n          logs.push(`Did commit [${props.count}]`);\n        });\n        return <span>{props.count}</span>;\n      }\n      render(<Counter count={0} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('0');\n      jest.runAllTimers();\n      expect(logs).toEqual(['Did commit [0]']);\n\n      logs = [];\n      render(<Counter count={1} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('1');\n      // Effects are deferred until after the commit\n      jest.runAllTimers();\n      expect(logs).toEqual(['Did commit [1]']);\n    });\n\n\n    it('flushes passive effects even with sibling deletions', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function LayoutEffect(props) {\n        useLayoutEffect(() => {\n          logs.push('Layout effect');\n        });\n        logs.push('Layout');\n        return <span>Layout</span>;\n      }\n      function PassiveEffect(props) {\n        useEffect(() => {\n          logs.push('Passive effect');\n        }, []);\n        logs.push('Passive');\n        return <span>Passive</span>;\n      }\n      let passive = <PassiveEffect key=\"p\" />;\n      render([<LayoutEffect key=\"l\" />, passive], container);\n      expect(logs).toEqual(['Layout', 'Passive', 'Layout effect']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Layout');\n      expect(container.childNodes[1].childNodes[0].data).toEqual('Passive');\n\n      logs = [];\n      // Destroying the first child shouldn't prevent the passive effect from\n      // being executed\n      render([passive], container);\n      jest.runAllTimers();\n      expect(logs).toEqual(['Passive effect']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Passive');\n\n      // (No effects are left to flush.)\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual([]);\n    });\n\n    it('flushes passive effects even if siblings schedule an update', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function PassiveEffect(props) {\n        useEffect(() => {\n          logs.push('Passive effect');\n        });\n        logs.push('Passive');\n        return <span>Passive</span>;\n      }\n      function LayoutEffect(props) {\n        let [count, setCount] = useState(0);\n        useLayoutEffect(() => {\n          // Scheduling work shouldn't interfere with the queued passive effect\n          if (count === 0) {\n            setCount(1);\n          }\n          logs.push('Layout effect ' + count);\n        });\n        logs.push('Layout');\n        return <span>Layout</span>;\n      }\n      render([<PassiveEffect key=\"p\" />, <LayoutEffect key=\"l\" />], container);\n      jest.runAllTimers();\n      expect(logs).toEqual([\n        'Passive',\n        'Layout',\n        'Layout effect 0',\n        'Passive effect',\n        'Layout',\n        'Layout effect 1',\n      ]);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Passive');\n      expect(container.childNodes[1].childNodes[0].data).toEqual('Layout');\n    });\n\n    it('flushes passive effects even if siblings schedule a new root', () => {\n      const container = createNodeElement('div');\n      const container2 = createNodeElement('div');\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function PassiveEffect(props) {\n        useEffect(() => {\n          logs.push('Passive effect');\n        }, []);\n        return <Text text=\"Passive\" />;\n      }\n      function LayoutEffect(props) {\n        useLayoutEffect(() => {\n          logs.push('Layout effect');\n          // Scheduling work shouldn't interfere with the queued passive effect\n          render(<Text text=\"New Root\" />, container2);\n        });\n        return <Text text=\"Layout\" />;\n      }\n      render([<PassiveEffect key=\"p\" />, <LayoutEffect key=\"l\" />], container);\n      jest.runAllTimers();\n      expect(logs).toEqual([\n        'Passive',\n        'Layout',\n        'Layout effect',\n        'Passive effect',\n        'New Root',\n      ]);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Passive');\n      expect(container.childNodes[1].childNodes[0].data).toEqual('Layout');\n    });\n\n    it(\n      'flushes effects serially by flushing old effects before flushing ' +\n        \"new ones, if they haven't already fired\",\n      () => {\n        const container = createNodeElement('div');\n        let logs = [];\n        function Text(props) {\n          logs.push(props.text);\n          return <span>{props.text}</span>;\n        }\n        function getCommittedText() {\n          return container.childNodes[0].childNodes[0].data;\n        }\n\n        function Counter(props) {\n          useEffect(() => {\n            logs.push(\n              `Committed state when effect was fired: ${getCommittedText()}`,\n            );\n          });\n          return <Text text={props.count} />;\n        }\n        render(<Counter count={0} />, container);\n        expect(logs).toEqual([0]);\n        expect(container.childNodes[0].childNodes[0].data).toEqual('0');\n\n        // Before the effects have a chance to flush, schedule another update\n        logs = [];\n        render(<Counter count={1} />, container);\n        expect(logs).toEqual([\n          // The previous effect flushes before the reconciliation\n          'Committed state when effect was fired: 0',\n          1,\n        ]);\n        expect(container.childNodes[0].childNodes[0].data).toEqual('1');\n\n        logs = [];\n        jest.runAllTimers();\n        expect(logs).toEqual([\n          'Committed state when effect was fired: 1',\n        ]);\n      },\n    );\n\n    it('updates have async priority', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function Counter(props) {\n        const [count, updateCount] = useState('(empty)');\n        useEffect(\n          () => {\n            logs.push(`Schedule update [${props.count}]`);\n            updateCount(props.count);\n          },\n          [props.count],\n        );\n        return <Text text={'Count: ' + count} />;\n      }\n      render(<Counter count={0} />, container);\n      expect(logs).toEqual(['Count: (empty)']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: (empty)');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual(['Schedule update [0]', 'Count: 0']);\n\n      logs = [];\n      render(<Counter count={1} />, container);\n      expect(logs).toEqual(['Count: 0']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual(['Schedule update [1]', 'Count: 1']);\n    });\n\n    it('updates have async priority even if effects are flushed early', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function Counter(props) {\n        const [count, updateCount] = useState('(empty)');\n        useEffect(\n          () => {\n            logs.push(`Schedule update [${props.count}]`);\n            updateCount(props.count);\n          },\n          [props.count],\n        );\n        return <Text text={'Count: ' + count} />;\n      }\n      render(<Counter count={0} />, container);\n      expect(logs).toEqual(['Count: (empty)']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: (empty)');\n\n      logs = [];\n      // Rendering again should flush the previous commit's effects\n      jest.runAllTimers();\n      render(<Counter count={1} />, container);\n      expect(logs).toEqual(['Schedule update [0]', 'Count: 0', 'Count: 0']);\n\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual(['Schedule update [1]', 'Count: 1']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 1');\n    });\n\n    it('flushes serial effects before enqueueing work', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      let _updateCount;\n      function Counter(props) {\n        const [count, updateCount] = useState(0);\n        _updateCount = updateCount;\n        useEffect(() => {\n          logs.push('Will set count to 1');\n          updateCount(1);\n        }, []);\n        return <Text text={'Count: ' + count} />;\n      }\n\n      render(<Counter count={0} />, container);\n      expect(logs).toEqual(['Count: 0']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      logs = [];\n      // Enqueuing this update forces the passive effect to be flushed --\n      // updateCount(1) happens first, so 2 wins.\n      _updateCount(2);\n      jest.runAllTimers();\n      expect(logs).toEqual(['Will set count to 1', 'Count: 2']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 2');\n    });\n\n    it(\n      'in sync mode, useEffect is deferred and updates finish synchronously ' +\n        '(in a single batch)',\n      () => {\n        const container = createNodeElement('div');\n        let logs = [];\n        function Counter(props) {\n          const [count, updateCount] = useState('(empty)');\n          useEffect(\n            () => {\n              // Update multiple times. These should all be batched together in\n              // a single render.\n              updateCount(props.count);\n              updateCount(props.count);\n              updateCount(props.count);\n              updateCount(props.count);\n              updateCount(props.count);\n              updateCount(props.count);\n            },\n            [props.count],\n          );\n          logs.push('Count: ' + count);\n          return <span>{'Count: ' + count}</span>;\n        }\n        render(<Counter count={0} />, container);\n        // Even in sync mode, effects are deferred until after paint\n        expect(logs).toEqual(['Count: (empty)']);\n        expect(container.childNodes[0].childNodes[0].data).toEqual('Count: (empty)');\n        // Now fire the effects\n        logs = [];\n        jest.runAllTimers();\n        // There were multiple updates, but there should only be a\n        // single render\n        expect(logs).toEqual(['Count: 0']);\n        expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      },\n    );\n\n    it(\n      'in sync mode, useEffect is deferred and updates finish synchronously ' +\n        '(in a single batch with different state)',\n      () => {\n        const container = createNodeElement('div');\n        let logs = [];\n        function Counter(props) {\n          const [count, updateCount] = useState('(empty)');\n          useEffect(\n            () => {\n              // Update multiple times. These should all be batched together in\n              // a single render.\n              updateCount(2);\n              updateCount(3);\n              updateCount(4);\n              updateCount(5);\n              updateCount(6);\n              updateCount(7);\n            },\n            [props.count],\n          );\n          logs.push('Count: ' + count);\n          return <span>{'Count: ' + count}</span>;\n        }\n        render(<Counter count={0} />, container);\n        // Even in sync mode, effects are deferred until after paint\n        expect(logs).toEqual(['Count: (empty)']);\n        expect(container.childNodes[0].childNodes[0].data).toEqual('Count: (empty)');\n        // Now fire the effects\n        logs = [];\n        jest.runAllTimers();\n        // There were multiple updates, but there should only be a\n        // single render\n        expect(logs).toEqual(['Count: 7']);\n        expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 7');\n      },\n    );\n\n    it('unmounts previous effect', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function Counter(props) {\n        useEffect(() => {\n          logs.push(`Did create [${props.count}]`);\n          return () => {\n            logs.push(`Did destroy [${props.count}]`);\n          };\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      render(<Counter count={0} />, container);\n      expect(logs).toEqual(['Count: 0']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual(['Did create [0]']);\n\n      logs = [];\n      render(<Counter count={1} />, container);\n      expect(logs).toEqual(['Count: 1']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 1');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual([\n        'Did destroy [0]',\n        'Did create [1]',\n      ]);\n    });\n\n    it('unmounts on deletion', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function Counter(props) {\n        useEffect(() => {\n          logs.push(`Did create [${props.count}]`);\n          return () => {\n            logs.push(`Did destroy [${props.count}]`);\n          };\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      render(<Counter count={0} />, container);\n      expect(logs).toEqual(['Count: 0']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual(['Did create [0]']);\n\n      logs = [];\n      render(<div />, container);\n      expect(logs).toEqual(['Did destroy [0]']);\n      expect(container.childNodes[0].tagName).toEqual('DIV');\n    });\n\n    it('unmounts on deletion after skipped effect', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function Counter(props) {\n        useEffect(() => {\n          logs.push(`Did create [${props.count}]`);\n          return () => {\n            logs.push(`Did destroy [${props.count}]`);\n          };\n        }, []);\n        return <Text text={'Count: ' + props.count} />;\n      }\n      render(<Counter count={0} />, container);\n      expect(logs).toEqual(['Count: 0']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual(['Did create [0]']);\n\n      logs = [];\n      render(<Counter count={1} />, container);\n      expect(logs).toEqual(['Count: 1']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 1');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual([]);\n\n      logs = [];\n      render([], container);\n      expect(logs).toEqual(['Did destroy [0]']);\n      expect(container.childNodes).toEqual([]);\n    });\n\n    it('always fires effects if no dependencies are provided', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function effect() {\n        logs.push('Did create');\n        return () => {\n          logs.push('Did destroy');\n        };\n      }\n      function Counter(props) {\n        useEffect(effect);\n        return <Text text={'Count: ' + props.count} />;\n      }\n      render(<Counter count={0} />, container);\n      expect(logs).toEqual(['Count: 0']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual(['Did create']);\n\n      logs = [];\n      render(<Counter count={1} />, container);\n      expect(logs).toEqual(['Count: 1']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 1');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual(['Did destroy', 'Did create']);\n\n      logs = [];\n      render([], container);\n      expect(logs).toEqual(['Did destroy']);\n      expect(container.childNodes).toEqual([]);\n    });\n\n    it('multiple effects', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function Counter(props) {\n        useEffect(() => {\n          logs.push(`Did commit 1 [${props.count}]`);\n        });\n        useEffect(() => {\n          logs.push(`Did commit 2 [${props.count}]`);\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      render(<Counter count={0} />, container);\n      expect(logs).toEqual(['Count: 0']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual([\n        'Did commit 1 [0]',\n        'Did commit 2 [0]',\n      ]);\n      logs = [];\n      render(<Counter count={1} />, container);\n      expect(logs).toEqual(['Count: 1']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 1');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual([\n        'Did commit 1 [1]',\n        'Did commit 2 [1]',\n      ]);\n    });\n\n    it('unmounts all previous effects before creating any new ones', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function Counter(props) {\n        useEffect(() => {\n          logs.push(`Mount A [${props.count}]`);\n          return () => {\n            logs.push(`Unmount A [${props.count}]`);\n          };\n        });\n        useEffect(() => {\n          logs.push(`Mount B [${props.count}]`);\n          return () => {\n            logs.push(`Unmount B [${props.count}]`);\n          };\n        });\n        return <Text text={'Count: ' + props.count} />;\n      }\n      render(<Counter count={0} />, container);\n      expect(logs).toEqual(['Count: 0']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual(['Mount A [0]', 'Mount B [0]']);\n      logs = [];\n      render(<Counter count={1} />, container);\n      expect(logs).toEqual(['Count: 1']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 1');\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual([\n        'Unmount A [0]',\n        'Mount A [1]',\n        'Unmount B [0]',\n        'Mount B [1]',\n      ]);\n    });\n\n    it('works with memo', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function Counter({count}) {\n        useLayoutEffect(() => {\n          logs.push('Mount: ' + count);\n          return () => logs.push('Unmount: ' + count);\n        });\n        return <Text text={'Count: ' + count} />;\n      }\n      Counter = memo(Counter);\n\n      render(<Counter count={0} />, container);\n      expect(logs).toEqual(['Count: 0', 'Mount: 0']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n\n      logs = [];\n      render(<Counter count={1} />, container);\n      expect(logs).toEqual(['Count: 1', 'Unmount: 0', 'Mount: 1']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 1');\n\n      logs = [];\n      render([], container);\n      expect(logs).toEqual(['Unmount: 1']);\n      expect(container.childNodes).toEqual([]);\n    });\n\n    it('does not update one component twice (update' +\n    'by props or setState should be merge)', () => {\n      let container = createNodeElement('div');\n      let logs = [];\n      let updateChildA, updateChildB, updateParent;\n      let childAUpdateNum, childBUpdateNum, parentUpdateNum;\n      childAUpdateNum = childBUpdateNum = parentUpdateNum = 0;\n\n      const ChildA = function(props) {\n        childAUpdateNum++;\n        const [count, updateCount] = useState(0);\n        updateChildA = updateCount;\n        return <span>{count}</span>;\n      };\n\n      const ChildB = function(props) {\n        childBUpdateNum++;\n        const [count, updateCount] = useState(0);\n        updateChildB = updateCount;\n        return <span>{count}</span>;\n      };\n\n      const Parent = function(props) {\n        parentUpdateNum++;\n        const [count, updateCount] = useState(0);\n        updateParent = updateCount;\n        return [<span key={'child1'}>{count}</span>, <ChildA key={'child2'} />, <ChildB key={'child3'} />];\n      };\n\n      function App() {\n        useEffect(() => {\n          updateChildA(1);\n          updateChildA(2);\n          updateParent(3);\n          updateChildB(4);\n        });\n        return <Parent />;\n      }\n      render(<App />, container);\n      expect(childAUpdateNum).toEqual(1);\n      expect(parentUpdateNum).toEqual(1);\n      expect(childBUpdateNum).toEqual(1);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('0');\n      expect(container.childNodes[1].childNodes[0].data).toEqual('0');\n      expect(container.childNodes[2].childNodes[0].data).toEqual('0');\n      jest.runAllTimers();\n      expect(childAUpdateNum).toEqual(2);\n      expect(parentUpdateNum).toEqual(2);\n      expect(childBUpdateNum).toEqual(2);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('3');\n      expect(container.childNodes[1].childNodes[0].data).toEqual('2');\n      expect(container.childNodes[2].childNodes[0].data).toEqual('4');\n    });\n  });\n\n  describe('useLayoutEffect', () => {\n    it('force flushes passive effects before firing new layout effects', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n      let committedText = '(empty)';\n      function Counter(props) {\n        useLayoutEffect(() => {\n          // Normally this would go in a mutation effect, but this test\n          // intentionally omits a mutation effect.\n          committedText = props.count + '';\n\n          logs.push(`Mount layout [current: ${committedText}]`);\n          return () => {\n            logs.push(`Unmount layout [current: ${committedText}]`);\n          };\n        });\n        useEffect(() => {\n          logs.push(`Mount normal [current: ${committedText}]`);\n          return () => {\n            logs.push(`Unmount normal [current: ${committedText}]`);\n          };\n        });\n        return null;\n      }\n\n      render(<Counter count={0} />, container);\n      expect(logs).toEqual(['Mount layout [current: 0]']);\n      expect(committedText).toEqual('0');\n\n      logs = [];\n      render(<Counter count={1} />, container);\n      expect(logs).toEqual([\n        'Mount normal [current: 0]',\n        'Unmount layout [current: 0]',\n        'Mount layout [current: 1]',\n      ]);\n      expect(committedText).toEqual('1');\n\n      logs = [];\n      jest.runAllTimers();\n      expect(logs).toEqual([\n        'Unmount normal [current: 1]',\n        'Mount normal [current: 1]',\n      ]);\n    });\n  });\n\n  describe('useMemo', () => {\n    it('memoizes value by comparing to previous inputs', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n\n      function CapitalizedText(props) {\n        const text = props.text;\n        const capitalizedText = useMemo(\n          () => {\n            logs.push(`Capitalize '${text}'`);\n            return text.toUpperCase();\n          },\n          [text],\n        );\n        return <Text text={capitalizedText} />;\n      }\n\n      render(<CapitalizedText text=\"hello\" />, container);\n      expect(logs).toEqual([\"Capitalize 'hello'\", 'HELLO']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('HELLO');\n\n      logs = [];\n      render(<CapitalizedText text=\"hi\" />, container);\n      expect(logs).toEqual([\"Capitalize 'hi'\", 'HI']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('HI');\n\n      logs = [];\n      render(<CapitalizedText text=\"hi\" />, container);\n      expect(logs).toEqual(['HI']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('HI');\n\n      logs = [];\n      render(<CapitalizedText text=\"goodbye\" />, container);\n      expect(logs).toEqual([\"Capitalize 'goodbye'\", 'GOODBYE']);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('GOODBYE');\n    });\n\n    it('always re-computes if no inputs are provided', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function LazyCompute(props) {\n        const computed = useMemo(props.compute);\n        return <Text text={computed} />;\n      }\n\n      function computeA() {\n        logs.push('compute A');\n        return 'A';\n      }\n\n      function computeB() {\n        logs.push('compute B');\n        return 'B';\n      }\n\n      render(<LazyCompute compute={computeA} />, container);\n      expect(logs).toEqual(['compute A', 'A']);\n\n      logs = [];\n      render(<LazyCompute compute={computeA} />, container);\n      expect(logs).toEqual(['compute A', 'A']);\n\n      logs = [];\n      render(<LazyCompute compute={computeA} />, container);\n      expect(logs).toEqual(['compute A', 'A']);\n\n      logs = [];\n      render(<LazyCompute compute={computeB} />, container);\n      expect(logs).toEqual(['compute B', 'B']);\n    });\n\n    it('should not invoke memoized function during re-renders unless inputs change', () => {\n      const container = createNodeElement('div');\n      let logs = [];\n\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n      function LazyCompute(props) {\n        const computed = useMemo(() => props.compute(props.input), [\n          props.input,\n        ]);\n        const [count, setCount] = useState(0);\n        if (count < 3) {\n          setCount(count + 1);\n        }\n        return <Text text={computed} />;\n      }\n\n      function compute(val) {\n        logs.push('compute ' + val);\n        return val;\n      }\n\n      render(<LazyCompute compute={compute} input=\"A\" />, container);\n      expect(logs).toEqual(['compute A', 'A']);\n\n      logs = [];\n      render(<LazyCompute compute={compute} input=\"A\" />, container);\n      expect(logs).toEqual(['A']);\n\n      logs = [];\n      render(<LazyCompute compute={compute} input=\"B\" />, container);\n      expect(logs).toEqual(['compute B', 'B']);\n    });\n  });\n\n  describe('useImperativeHandle', () => {\n    it('does not update when deps are the same', () => {\n      const container = createNodeElement('div');\n      const INCREMENT = 'INCREMENT';\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n\n      function reducer(state, action) {\n        return action === INCREMENT ? state + 1 : state;\n      }\n\n      function Counter(props, ref) {\n        const [count, dispatch] = useReducer(reducer, 0);\n        useImperativeHandle(ref, () => ({count, dispatch}), []);\n        return <Text text={'Count: ' + count} />;\n      }\n\n      Counter = forwardRef(Counter);\n      const counter = createRef(null);\n      render(<Counter ref={counter} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      expect(counter.current.count).toBe(0);\n\n      counter.current.dispatch(INCREMENT);\n      jest.runAllTimers();\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 1');\n      // Intentionally not updated because of [] deps:\n      expect(counter.current.count).toBe(0);\n    });\n\n    it('automatically updates when deps are not specified', () => {\n      const container = createNodeElement('div');\n      const INCREMENT = 'INCREMENT';\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n\n      function reducer(state, action) {\n        return action === INCREMENT ? state + 1 : state;\n      }\n\n      function Counter(props, ref) {\n        const [count, dispatch] = useReducer(reducer, 0);\n        useImperativeHandle(ref, () => ({count, dispatch}));\n        return <Text text={'Count: ' + count} />;\n      }\n\n      Counter = forwardRef(Counter);\n      const counter = createRef(null);\n      render(<Counter ref={counter} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      expect(counter.current.count).toBe(0);\n\n      counter.current.dispatch(INCREMENT);\n      jest.runAllTimers();\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 1');\n      expect(counter.current.count).toBe(1);\n    });\n\n    it('updates when deps are different', () => {\n      const container = createNodeElement('div');\n      const INCREMENT = 'INCREMENT';\n      let logs = [];\n      function Text(props) {\n        logs.push(props.text);\n        return <span>{props.text}</span>;\n      }\n\n      function reducer(state, action) {\n        return action === INCREMENT ? state + 1 : state;\n      }\n\n      let totalRefUpdates = 0;\n      function Counter(props, ref) {\n        const [count, dispatch] = useReducer(reducer, 0);\n        useImperativeHandle(\n          ref,\n          () => {\n            totalRefUpdates++;\n            return {count, dispatch};\n          },\n          [count],\n        );\n        return <Text text={'Count: ' + count} />;\n      }\n\n      Counter = forwardRef(Counter);\n      const counter = createRef(null);\n      render(<Counter ref={counter} />, container);\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 0');\n      expect(counter.current.count).toBe(0);\n      expect(totalRefUpdates).toBe(1);\n\n      counter.current.dispatch(INCREMENT);\n      jest.runAllTimers();\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 1');\n      expect(counter.current.count).toBe(1);\n      expect(totalRefUpdates).toBe(2);\n\n      // Update that doesn't change the ref dependencies\n      render(<Counter ref={counter} />, container);\n      jest.runAllTimers();\n      expect(container.childNodes[0].childNodes[0].data).toEqual('Count: 1');\n      expect(counter.current.count).toBe(1);\n      expect(totalRefUpdates).toBe(2); // Should not increase since last time\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/__tests__/memo.js",
    "content": "/* @jsx createElement */\n\nimport createElement from '../createElement';\nimport Host from '../vdom/host';\nimport render from '../render';\nimport ServerDriver from 'driver-server';\nimport memo from '../memo';\n\ndescribe('memo', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n  });\n\n  it('will only shallowly compare complex objects in the props object', () => {\n    const container = createNodeElement('div');\n    let renderCounter1 = 0;\n    let renderCounter2 = 0;\n\n    function App(props) {\n      renderCounter1++;\n      return <span>{props.value}</span>;\n    }\n\n    App = memo(App);\n\n    function Outer(props) {\n      renderCounter2++;\n      return <App value={props.value} />;\n    }\n\n    render(<Outer value={1} />, container);\n    expect(renderCounter1).toEqual(1);\n    expect(renderCounter2).toEqual(1);\n\n    render(<Outer value={2} />, container);\n    expect(renderCounter1).toEqual(2);\n    expect(renderCounter2).toEqual(2);\n\n    render(<Outer value={2} />, container);\n    expect(renderCounter1).toEqual(2);\n    expect(renderCounter2).toEqual(3);\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/__tests__/render.js",
    "content": "/* @jsx createElement */\n\nimport createElement from '../createElement';\nimport Host from '../vdom/host';\nimport render from '../render';\nimport ServerDriver from 'driver-server';\nimport Component from '../vdom/component';\n\ndescribe('render', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('render to default container', () => {\n    let appendChildMock = jest.fn();\n\n    Host.driver = {\n      createElement() {\n        return {tagName: 'DIV'};\n      },\n      createBody() {\n        return {tagName: 'BODY'};\n      },\n      appendChild: appendChildMock\n    };\n\n    render(<div />);\n\n    let call = appendChildMock.mock.calls[0];\n    expect(call[0].tagName).toBe('DIV');\n    expect(call[1].tagName).toBe('BODY');\n  });\n\n  it('should render different components in same root', function() {\n    let container = createNodeElement('container');\n\n    render(<div />, container);\n    expect(container.childNodes[0].tagName).toBe('DIV');\n\n    render(<span />, container);\n    expect(container.childNodes[0].tagName).toBe('SPAN');\n  });\n\n  it('should reuse markup if rendering to the same target twice', function() {\n    let container = createNodeElement('container');\n    let instance1 = render(<div />, container);\n    let instance2 = render(<div />, container);\n\n    expect(instance1 === instance2).toBe(true);\n  });\n\n  it('should trigger afterRender twice when render to the same target twice', () => {\n    let beforeRenderCount = 0;\n    let afterRenderCount = 0;\n    let container = createNodeElement('container');\n    Host.driver = Object.assign({}, Host.driver, {\n      beforeRender() {\n        beforeRenderCount += 1;\n      },\n      afterRender() {\n        afterRenderCount += 1;\n      },\n    });\n\n    render(<div />, container);\n    render(<span />, container);\n\n    expect(beforeRenderCount).toBe(2);\n    expect(afterRenderCount).toBe(2);\n  });\n\n  it('should not throw error when have callback and options is null', function(done) {\n    let container = createNodeElement('container');\n    render(<div />, container, function() {\n      done();\n    });\n  });\n\n  it('should not re-render when element is same in same root', function() {\n    let container = createNodeElement('container');\n    let updatedCount = 0;\n    let App = function() {\n      updatedCount++;\n      return <div />;\n    };\n    let CacheApp = <App />;\n\n    render(CacheApp, container);\n    expect(container.childNodes[0].tagName).toBe('DIV');\n    expect(updatedCount).toBe(1);\n    render(CacheApp, container);\n    expect(container.childNodes[0].tagName).toBe('DIV');\n    expect(updatedCount).toBe(1);\n  });\n\n  it('render in the life cycle should in a batch', function() {\n    let container = createNodeElement('div');\n    let container2 = createNodeElement('div');\n\n    const Child = jest.fn(function(props) {\n      return <span>{props.number}</span>;\n    });\n\n    class App extends Component {\n      componentDidMount() {\n        render(<Child number=\"1\" />, container2);\n        render(<Child number=\"2\" />, container2);\n        render(<Child number=\"3\" />, container2);\n        render(<Child number=\"4\" />, container2);\n        expect(container2.childNodes).toEqual([]);\n      }\n      render() {\n        return <span />;\n      }\n    }\n    render(<App />, container);\n    jest.runAllTimers();\n    expect(Child).toHaveBeenCalledTimes(1);\n    expect(container2.childNodes[0].childNodes[0].data).toBe('4');\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/assign.js",
    "content": "export default Object.assign;\n"
  },
  {
    "path": "packages/rax/src/compat/index.js",
    "content": "import * as RaxCore from 'rax'; // eslint-disable-line\nimport Children from 'rax-children';\nimport isValidElement from 'rax-is-valid-element';\nimport createFactory from 'rax-create-factory';\nimport cloneElement from 'rax-clone-element';\n\nconst Rax = RaxCore;\n\nRax.Children = Children;\nRax.isValidElement = isValidElement;\nRax.createFactory = createFactory;\nRax.cloneElement = cloneElement;\nRax.Component.prototype.isReactComponent = {};\n\nexport * from 'rax'; // eslint-disable-line\nexport {\n  Children,\n  isValidElement,\n  createFactory,\n  cloneElement,\n};\nexport default Rax;\n"
  },
  {
    "path": "packages/rax/src/constant.js",
    "content": "/* Common constant variables for rax */\n\nexport const INTERNAL = '_internal';\nexport const INSTANCE = '_instance';\nexport const NATIVE_NODE = '_nativeNode';\nexport const RENDERED_COMPONENT = '_renderedComponent';\n"
  },
  {
    "path": "packages/rax/src/createContext.js",
    "content": "import invokeFunctionsWithContext from './invokeFunctionsWithContext';\nimport { useState, useLayoutEffect } from './hooks';\nimport { isFunction } from './types';\nimport toArray from './toArray';\nimport getNearestParent from './vdom/getNearestParent';\n\nlet id = 0;\n\nexport default function createContext(defaultValue) {\n  const contextID = '_c' + id++;\n\n  // Provider Component\n  class Provider {\n    constructor() {\n      this.__contextID = contextID;\n      this.__handlers = [];\n    }\n    __on(handler) {\n      this.__handlers.push(handler);\n    }\n    __off(handler) {\n      this.__handlers = this.__handlers.filter(h => h !== handler);\n    }\n    // Like getChildContext but called in SSR\n    _getChildContext() {\n      return {\n        [contextID]: this\n      };\n    }\n    // `getValue()` called in rax-server-renderer\n    getValue() {\n      return this.props.value !== undefined ? this.props.value : defaultValue;\n    }\n    componentDidUpdate(prevProps) {\n      if (this.props.value !== prevProps.value) {\n        invokeFunctionsWithContext(this.__handlers, null, this.getValue());\n      }\n    }\n    render() {\n      return this.props.children;\n    }\n  }\n\n  function getNearestParentProvider(instance) {\n    return getNearestParent(instance, parent => parent.__contextID === contextID);\n  }\n\n  // Consumer Component\n  function Consumer(props, context) {\n    // Current `context[contextID]` only works in SSR\n    const [provider] = useState(() => context[contextID] || getNearestParentProvider(this));\n    let value = provider ? provider.getValue() : defaultValue;\n    const [prevValue, setValue] = useState(value);\n\n    if (value !== prevValue) {\n      setValue(value);\n      return; // Interrupt execution of consumer.\n    }\n\n    useLayoutEffect(() => {\n      if (provider) {\n        provider.__on(setValue);\n        return () => {\n          provider.__off(setValue);\n        };\n      }\n    }, []);\n\n    // Consumer requires a function as a child.\n    // The function receives the current context value.\n    const consumer = toArray(props.children)[0];\n    if (isFunction(consumer)) {\n      return consumer(value);\n    }\n  }\n\n  return {\n    Provider,\n    Consumer,\n    // `_contextID` and `_defaultValue` accessed in rax-server-renderer\n    _contextID: contextID,\n    _defaultValue: defaultValue,\n    __getNearestParentProvider: getNearestParentProvider,\n  };\n}\n"
  },
  {
    "path": "packages/rax/src/createElement.js",
    "content": "import Host from './vdom/host';\nimport Element from './vdom/element';\nimport flattenChildren from './vdom/flattenChildren';\nimport { warning, throwError, throwMinifiedWarn } from './error';\nimport { isString, isArray, NOOP } from './types';\nimport validateChildKeys from './validateChildKeys';\n\nconst RESERVED_PROPS = {\n  key: true,\n  ref: true,\n};\n\nexport default function createElement(type, config, children) {\n  // Reserved names are extracted\n  let props = {};\n  let propName;\n  let key = null;\n  let ref = null;\n\n  if (config != null) {\n    ref = config.ref === undefined ? null : config.ref;\n    key = config.key === undefined ? null : '' + config.key;\n\n    // Remaining properties are added to a new props object\n    for (propName in config) {\n      if (!RESERVED_PROPS[propName]) {\n        props[propName] = config[propName];\n      }\n    }\n  }\n\n  // Children arguments can be more than one\n  const childrenLength = arguments.length - 2;\n  if (childrenLength > 0) {\n    if (childrenLength === 1 && !isArray(children)) {\n      props.children = children;\n    } else {\n      let childArray = children;\n      if (childrenLength > 1) {\n        childArray = new Array(childrenLength);\n        for (var i = 0; i < childrenLength; i++) {\n          childArray[i] = arguments[i + 2];\n        }\n      }\n      props.children = flattenChildren(childArray);\n    }\n  }\n\n  // Resolve default props\n  if (type && type.defaultProps) {\n    let defaultProps = type.defaultProps;\n    for (propName in defaultProps) {\n      if (props[propName] === undefined) {\n        props[propName] = defaultProps[propName];\n      }\n    }\n  }\n\n  if (type == null) {\n    if (process.env.NODE_ENV !== 'production') {\n      throwError(`Invalid element type, expected a string or a class/function component but got \"${type}\".`);\n    } else {\n      // A empty component replaced avoid break render in production\n      type = NOOP;\n      throwMinifiedWarn(0);\n    }\n  }\n\n  if (process.env.NODE_ENV !== 'production') {\n    if (isString(ref) && !Host.owner) {\n      warning(\n        `Adding a string ref \"${ref}\" that was not created inside render method, or multiple copies of Rax are used.`\n      );\n    }\n\n    for (let i = 2; i < arguments.length; i ++) {\n      validateChildKeys(arguments[i], type);\n    }\n  }\n\n  return new Element(\n    type,\n    key,\n    ref,\n    props,\n    Host.owner\n  );\n}\n\n"
  },
  {
    "path": "packages/rax/src/createRef.js",
    "content": "export default function createRef() {\n  return {\n    current: null\n  };\n}"
  },
  {
    "path": "packages/rax/src/debug/dump.js",
    "content": "import Host from '../vdom/host';\nimport getComponentTree from './getComponentTree';\n\nconst INDENTATION_SIZE = 2;\nconst MAX_DEPTH = 2;\nconst MAX_STRING_LENGTH = 50;\n\n/**\n * Dump all Native root views and their content. This function tries\n * it best to get the content but ultimately relies on implementation details\n * of  and will fail in future versions.\n */\nfunction dumpTree() {\n  try {\n    return getDumpTree();\n  } catch (e) {\n    return 'Failed to dump tree: ' + e;\n  }\n}\n\nfunction getDumpTree() {\n  let output = '';\n  const rootIds = Object.getOwnPropertyNames(Host.rootComponents);\n  for (const rootId of rootIds) {\n    const inst = Host.rootInstances[rootId];\n    output += `============ Root ID: ${rootId} ============\\n`;\n    output += dumpNode(inst.getRenderedComponent(), 0);\n    output += `============ End root ID: ${rootId} ============\\n`;\n  }\n  return output;\n}\n\nfunction dumpNode(node, identation) {\n  const data = getComponentTree(node);\n  if (data.nodeType === 'Text') {\n    return indent(identation) + data.text + '\\n';\n  } else if (data.nodeType === 'Empty') {\n    return '';\n  }\n  let output = indent(identation) + `<${data.name}`;\n  if (data.nodeType === 'Composite') {\n    for (const propName of Object.getOwnPropertyNames(data.props || {})) {\n      if (isNormalProp(propName)) {\n        try {\n          const value = convertValue(data.props[propName]);\n          if (value) {\n            output += ` ${propName}=${value}`;\n          }\n        } catch (e) {\n          const message = `[Failed to get property: ${e}]`;\n          output += ` ${propName}=${message}`;\n        }\n      }\n    }\n  }\n  let childOutput = '';\n  for (const child of data.children || []) {\n    childOutput += dumpNode(child, identation + 1);\n  }\n\n  if (childOutput) {\n    output += '>\\n' + childOutput + indent(identation) + `</${data.name}>\\n`;\n  } else {\n    output += ' />\\n';\n  }\n\n  return output;\n}\n\nfunction isNormalProp(name) {\n  switch (name) {\n    case 'children':\n    case 'key':\n    case 'ref':\n      return false;\n    default:\n      return true;\n  }\n}\n\nfunction convertObject(object, depth) {\n  if (depth >= MAX_DEPTH) {\n    return '[...omitted]';\n  }\n  let output = '{';\n  let first = true;\n  for (const key of Object.getOwnPropertyNames(object)) {\n    if (!first) {\n      output += ', ';\n    }\n    // $FlowFixMe(>=0.28.0)\n    output += `${key}: ${convertValue(object[key], depth + 1)}`;\n    first = false;\n  }\n  return output + '}';\n}\n\nfunction convertValue(value, depth = 0) {\n  if (!value) {\n    return null;\n  }\n\n  switch (typeof value) {\n    case 'string':\n      return JSON.stringify(possiblyEllipsis(value).replace('\\n', '\\\\n'));\n    case 'boolean':\n    case 'number':\n      return JSON.stringify(value);\n    case 'function':\n      return '[function]';\n    case 'object':\n      return convertObject(value, depth);\n    default:\n      return null;\n  }\n}\n\nfunction possiblyEllipsis(value) {\n  if (value.length > MAX_STRING_LENGTH) {\n    return value.slice(0, MAX_STRING_LENGTH) + '...';\n  } else {\n    return value;\n  }\n}\n\nfunction indent(size) {\n  return ' '.repeat(size * INDENTATION_SIZE);\n}\n\nexport default dumpTree;\n"
  },
  {
    "path": "packages/rax/src/debug/getComponentTree.js",
    "content": "import { INSTANCE, RENDERED_COMPONENT } from '../constant';\n\nconst CURRENT_ELEMENT = '__currentElement';\n\nexport default function getComponentTree(element) {\n  var children = null;\n  var props = null;\n  var state = null;\n  var context = null;\n  var name = null;\n  var type = null;\n  var text = null;\n  var nodeType = 'Native';\n  // If the parent is a native node without rendered children, but with\n  // multiple string children, then the `element` that gets passed in here is\n  // a plain value -- a string or number.\n  if (typeof element !== 'object') {\n    nodeType = 'Text';\n    text = element + '';\n  } else if (element[CURRENT_ELEMENT] === null || element[CURRENT_ELEMENT] === false) {\n    nodeType = 'Empty';\n  } else if (element[RENDERED_COMPONENT]) {\n    nodeType = 'NativeWrapper';\n    children = [element[RENDERED_COMPONENT]];\n    props = element[INSTANCE].props;\n    state = element[INSTANCE].state;\n    context = element[INSTANCE].context;\n    if (context && Object.keys(context).length === 0) {\n      context = null;\n    }\n  } else if (element[RENDERED_COMPONENT]) {\n    children = childrenList(element[RENDERED_COMPONENT]);\n  } else if (element[CURRENT_ELEMENT] && element[CURRENT_ELEMENT].props) {\n    // This is a native node without rendered children -- meaning the children\n    // prop is just a string or (in the case of the <option>) a list of\n    // strings & numbers.\n    children = element[CURRENT_ELEMENT].props.children;\n  }\n\n  if (!props && element[CURRENT_ELEMENT] && element[CURRENT_ELEMENT].props) {\n    props = element[CURRENT_ELEMENT].props;\n  }\n\n  // != used deliberately here to catch undefined and null\n  if (element[CURRENT_ELEMENT] != null) {\n    type = element[CURRENT_ELEMENT].type;\n    if (typeof type === 'string') {\n      name = type;\n    } else if (element.getName) {\n      nodeType = 'Composite';\n      name = element.getName();\n      // 0.14 top-level wrapper\n      // TODO(jared): The backend should just act as if these don't exist.\n      if (element._renderedComponent && element[CURRENT_ELEMENT].props === element._renderedComponent[CURRENT_ELEMENT]) {\n        nodeType = 'Wrapper';\n      }\n      if (name === null) {\n        name = 'No display name';\n      }\n    } else if (element._text) {\n      nodeType = 'Text';\n      text = element._text;\n    } else {\n      name = type.displayName || type.name || 'Unknown';\n    }\n  }\n\n  if (element[INSTANCE]) {\n    // TODO: React ART currently falls in this bucket, but this doesn't\n    // actually make sense and we should clean this up after stabilizing our\n    // API for backends\n    let inst = element[INSTANCE];\n    if (inst[RENDERED_COMPONENT]) {\n      children = childrenList(inst[RENDERED_COMPONENT]);\n    }\n  }\n\n  return {\n    nodeType,\n    type,\n    name,\n    props,\n    state,\n    context,\n    children,\n    text\n  };\n}\n\nfunction childrenList(children) {\n  var res = [];\n  for (var name in children) {\n    res.push(children[name]);\n  }\n  return res;\n}\n"
  },
  {
    "path": "packages/rax/src/devtools/index.js",
    "content": "import Instance from '../vdom/instance';\nimport Host from '../vdom/host';\nimport Reconciler from './reconciler';\nimport { RENDERED_COMPONENT } from '../constant';\n\nconst DevtoolsHook = {\n  ComponentTree: {\n    getClosestInstanceFromNode(node) {\n      return Instance.get(node);\n    },\n    getNodeFromInstance(inst) {\n      // inst is an internal instance (but could be a composite)\n      while (inst[RENDERED_COMPONENT]) {\n        inst = inst[RENDERED_COMPONENT];\n      }\n\n      if (inst) {\n        return inst._nativeNode;\n      } else {\n        return null;\n      }\n    }\n  },\n  Mount: {\n    get _instancesByReactRootID() {\n      const rootComponents = {};\n\n      // Ignore display top-level root component\n      for (let rootID in Host.rootComponents) {\n        rootComponents[rootID] = Host.rootComponents[rootID][RENDERED_COMPONENT];\n      }\n\n      return rootComponents;\n    },\n\n    _renderNewRootComponent: Reconciler.renderNewRootComponent\n  },\n  Reconciler,\n  // monitor the info of all components\n  monitor: null\n};\n\nexport default DevtoolsHook;\n"
  },
  {
    "path": "packages/rax/src/devtools/reconciler.js",
    "content": "export default {\n  // Stubs - DevTools expects to find these methods and replace them\n  // with wrappers in order to observe components being mounted, updated and\n  // unmounted\n  mountComponent() {},\n  receiveComponent() {},\n  unmountComponent() {},\n  // Stub - DevTools expects to find this method and replace it\n  // with a wrapper in order to observe new root components being added\n  renderNewRootComponent() {},\n};\n"
  },
  {
    "path": "packages/rax/src/error.js",
    "content": "import Host from './vdom/host';\nimport { scheduler } from './vdom/scheduler';\nimport { NOOP, isPlainObject } from './types';\n\nfunction createMinifiedError(type, code, obj) {\n  var typeInfo = obj === undefined ? '' : ' got: ' + getTypeInfo(obj);\n  return new Error(`${type}: #${code}, ${getRenderErrorInfo()}.` + typeInfo);\n}\n\nexport function getTypeInfo(obj) {\n  return isPlainObject(obj) ? Object.keys(obj) : obj;\n}\n\nexport function getRenderErrorInfo() {\n  const ownerComponent = Host.owner;\n  return ownerComponent ? `check <${ownerComponent.__getName()}>` : 'no owner';\n}\n\n/**\n * Minified code:\n *  1: Hooks called outside a component, or multiple version of Rax are used.\n *  6: Invalid component type, expected a class or function component.\n *  4: Too many re-renders, the number of renders is limited to prevent an infinite loop.\n *  5: Rax driver not found.\n * @param code {Number}\n * @param obj {Object}\n */\nexport function throwMinifiedError(code, obj) {\n  throw createMinifiedError('Error', code, obj);\n}\n\n/**\n * Minified Code:\n * 0: Invalid element type, expected a string or a class/function component but got \"null\" or \"undefined\".\n * 2. Invalid child type, expected types: Element instance, string, boolean, array, null, undefined.\n * 3. Ref can not attach because multiple copies of Rax are used.\n * @param {number} code\n * @param {string} info\n */\nexport function throwMinifiedWarn(code, obj) {\n  let err = createMinifiedError('Warn', code, obj);\n  scheduler(() => {\n    throw err;\n  }, 0);\n}\n\nexport function throwError(message, obj) {\n  let typeInfo = obj === undefined ? '' :\n    '(found: ' + (isPlainObject(obj) ? `object with keys {${Object.keys(obj)}}` : obj) + ')';\n\n  throw Error(`${message} ${typeInfo}`);\n}\n\nexport let warning = NOOP;\n\nif (process.env.NODE_ENV !== 'production') {\n  warning = (template, ...args) => {\n    if (typeof console !== 'undefined') {\n      let argsWithFormat = args.map(item => '' + item);\n      argsWithFormat.unshift('Warning: ' + template);\n      // Don't use spread (or .apply) directly because it breaks IE9\n      Function.prototype.apply.call(console.error, console, argsWithFormat);\n    }\n\n    // For works in DevTools when enable `Pause on caught exceptions`\n    // that can find the component where caused this warning\n    try {\n      let argIndex = 0;\n      const message = 'Warning: ' + template.replace(/%s/g, () => args[argIndex++]);\n      throw new Error(message);\n    } catch (e) {}\n  };\n}\n\n"
  },
  {
    "path": "packages/rax/src/forwardRef.js",
    "content": "export default function(render) {\n  // _forwardRef is also use in rax server renderer\n  render._forwardRef = true;\n  return render;\n}"
  },
  {
    "path": "packages/rax/src/fragment.js",
    "content": "export default function Fragment(props) {\n  return props.children;\n}"
  },
  {
    "path": "packages/rax/src/hooks.js",
    "content": "import Host from './vdom/host';\nimport { scheduleEffect, flushEffect } from './vdom/scheduler';\nimport { is } from './vdom/shallowEqual';\nimport { isArray, isFunction, isNull } from './types';\nimport { warning, throwError, throwMinifiedError } from './error';\nimport { INSTANCE } from './constant';\n\nfunction getCurrentInstance() {\n  return Host.owner && Host.owner[INSTANCE];\n}\n\nfunction getCurrentRenderingInstance() {\n  const currentInstance = getCurrentInstance();\n  if (currentInstance) {\n    return currentInstance;\n  } else {\n    if (process.env.NODE_ENV !== 'production') {\n      throwError('Hooks called outside a component, or multiple version of Rax are used.');\n    } else {\n      throwMinifiedError(1);\n    }\n  }\n}\n\nfunction areInputsEqual(inputs, prevInputs) {\n  if (isNull(prevInputs) || inputs.length !== prevInputs.length) {\n    return false;\n  }\n\n  for (let i = 0; i < inputs.length; i++) {\n    if (is(inputs[i], prevInputs[i])) {\n      continue;\n    }\n    return false;\n  }\n  return true;\n}\n\nexport function useState(initialState) {\n  const currentInstance = getCurrentRenderingInstance();\n  const hookID = currentInstance.getHookID();\n  const hooks = currentInstance.getHooks();\n\n  if (!hooks[hookID]) {\n    // If the initial state is the result of an expensive computation,\n    // you may provide a function instead for lazy initial state.\n    if (isFunction(initialState)) {\n      initialState = initialState();\n    }\n\n    const setState = newState => {\n      // Flush all effects first before update state\n      if (!Host.__isUpdating) {\n        flushEffect();\n      }\n\n      const hook = hooks[hookID];\n      const eagerState = hook[2];\n      // function updater\n      if (isFunction(newState)) {\n        newState = newState(eagerState);\n      }\n\n      if (!is(newState, eagerState)) {\n        // Current instance is in render update phase.\n        // After this one render finish, will continue run.\n        hook[2] = newState;\n        if (getCurrentInstance() === currentInstance) {\n          // Marked as is scheduled that could finish hooks.\n          currentInstance.__isScheduled = true;\n        } else {\n          currentInstance.__update();\n        }\n      }\n    };\n\n    hooks[hookID] = [\n      initialState,\n      setState,\n      initialState\n    ];\n  }\n\n  const hook = hooks[hookID];\n  if (!is(hook[0], hook[2])) {\n    hook[0] = hook[2];\n    currentInstance.__shouldUpdate = true;\n  }\n\n  return hook;\n}\n\nexport function useContext(context) {\n  const currentInstance = getCurrentRenderingInstance();\n  return currentInstance.useContext(context);\n}\n\nexport function useEffect(effect, inputs) {\n  useEffectImpl(effect, inputs, true);\n}\n\nexport function useLayoutEffect(effect, inputs) {\n  useEffectImpl(effect, inputs);\n}\n\nfunction useEffectImpl(effect, inputs, defered) {\n  const currentInstance = getCurrentRenderingInstance();\n  const hookID = currentInstance.getHookID();\n  const hooks = currentInstance.getHooks();\n  inputs = inputs === undefined ? null : inputs;\n\n  if (!hooks[hookID]) {\n    const __create = (immediately) => {\n      if (!immediately && defered) return scheduleEffect(() => __create(true));\n      const { current } = __create;\n      if (current) {\n        __destory.current = current();\n        __create.current = null;\n\n        if (process.env.NODE_ENV !== 'production') {\n          const currentDestory = __destory.current;\n          if (currentDestory !== undefined && typeof currentDestory !== 'function') {\n            let msg;\n            if (currentDestory === null) {\n              msg =\n                ' You returned null. If your effect does not require clean ' +\n                'up, return undefined (or nothing).';\n            } else if (typeof currentDestory.then === 'function') {\n              msg =\n                '\\n\\nIt looks like you wrote useEffect(async () => ...) or returned a Promise. ' +\n                'Instead, write the async function inside your effect ' +\n                'and call it immediately:\\n\\n' +\n                'useEffect(() => {\\n' +\n                '  async function fetchData() {\\n' +\n                '    // You can await here\\n' +\n                '    const response = await MyAPI.getData(someId);\\n' +\n                '    // ...\\n' +\n                '  }\\n' +\n                '  fetchData();\\n' +\n                '}, [someId]); // Or [] if effect doesn\\'t need props or state.';\n            } else {\n              msg = ' You returned: ' + currentDestory;\n            }\n\n            warning(\n              'An effect function must not return anything besides a function, ' +\n              'which is used for clean-up.' + msg,\n            );\n          }\n        }\n      }\n    };\n\n    const __destory = (immediately) => {\n      if (!immediately && defered) return scheduleEffect(() => __destory(true));\n      const { current } = __destory;\n      if (current) {\n        current();\n        __destory.current = null;\n      }\n    };\n\n    __create.current = effect;\n\n    hooks[hookID] = {\n      __create,\n      __destory,\n      __prevInputs: inputs,\n      __inputs: inputs\n    };\n\n    currentInstance.didMount.push(__create);\n    currentInstance.willUnmount.push(() => __destory(true));\n    currentInstance.didUpdate.push(() => {\n      const { __prevInputs, __inputs, __create } = hooks[hookID];\n      if (__inputs == null || !areInputsEqual(__inputs, __prevInputs)) {\n        __destory();\n        __create();\n      }\n    });\n  } else {\n    const hook = hooks[hookID];\n    const { __create, __inputs: prevInputs } = hook;\n    hook.__inputs = inputs;\n    hook.__prevInputs = prevInputs;\n    __create.current = effect;\n  }\n}\n\nexport function useImperativeHandle(ref, create, inputs) {\n  const nextInputs = isArray(inputs) ? inputs.concat([ref]) : null;\n\n  useLayoutEffect(() => {\n    if (isFunction(ref)) {\n      ref(create());\n      return () => ref(null);\n    } else if (ref != null) {\n      ref.current = create();\n      return () => {\n        ref.current = null;\n      };\n    }\n  }, nextInputs);\n}\n\nexport function useRef(initialValue) {\n  const currentInstance = getCurrentRenderingInstance();\n  const hookID = currentInstance.getHookID();\n  const hooks = currentInstance.getHooks();\n\n  if (!hooks[hookID]) {\n    hooks[hookID] = {\n      current: initialValue\n    };\n  }\n\n  return hooks[hookID];\n}\n\nexport function useCallback(callback, inputs) {\n  return useMemo(() => callback, inputs);\n}\n\nexport function useMemo(create, inputs) {\n  const currentInstance = getCurrentRenderingInstance();\n  const hookID = currentInstance.getHookID();\n  const hooks = currentInstance.getHooks();\n  inputs = inputs === undefined ? null : inputs;\n\n  if (!hooks[hookID]) {\n    hooks[hookID] = [create(), inputs];\n  } else {\n    const prevInputs = hooks[hookID][1];\n    if (isNull(inputs) || !areInputsEqual(inputs, prevInputs)) {\n      hooks[hookID] = [create(), inputs];\n    }\n  }\n\n  return hooks[hookID][0];\n}\n\nexport function useReducer(reducer, initialArg, init) {\n  const currentInstance = getCurrentRenderingInstance();\n  const hookID = currentInstance.getHookID();\n  const hooks = currentInstance.getHooks();\n  const hook = hooks[hookID];\n\n  if (!hook) {\n    const initialState = isFunction(init) ? init(initialArg) : initialArg;\n\n    const dispatch = action => {\n      // Flush all effects first before update state\n      if (!Host.__isUpdating) {\n        flushEffect();\n      }\n\n      const hook = hooks[hookID];\n      // Reducer will update in the next render, before that we add all\n      // actions to the queue\n      const queue = hook[2];\n\n      if (getCurrentInstance() === currentInstance) {\n        queue.__actions.push(action);\n        currentInstance.__isScheduled = true;\n      } else {\n        const currentState = queue.__eagerState;\n        const eagerReducer = queue.__eagerReducer;\n        const eagerState = eagerReducer(currentState, action);\n        if (is(eagerState, currentState)) {\n          return;\n        }\n        queue.__eagerState = eagerState;\n        queue.__actions.push(action);\n        currentInstance.__update();\n      }\n    };\n\n    return hooks[hookID] = [\n      initialState,\n      dispatch,\n      {\n        __actions: [],\n        __eagerReducer: reducer,\n        __eagerState: initialState\n      }\n    ];\n  }\n\n  const queue = hook[2];\n  let next = hook[0];\n\n  if (currentInstance.__reRenders > 0) {\n    for (let i = 0; i < queue.__actions.length; i++) {\n      next = reducer(next, queue.__actions[i]);\n    }\n  } else {\n    next = queue.__eagerState;\n  }\n\n  if (!is(next, hook[0])) {\n    hook[0] = next;\n    currentInstance.__shouldUpdate = true;\n  }\n\n  queue.__eagerReducer = reducer;\n  queue.__eagerState = next;\n  queue.__actions.length = 0;\n\n  return hooks[hookID];\n}\n"
  },
  {
    "path": "packages/rax/src/index.js",
    "content": "export createElement from './createElement';\nexport createContext from './createContext';\nexport createRef from './createRef';\nexport forwardRef from './forwardRef';\nexport { useState, useContext, useEffect, useLayoutEffect, useRef, useCallback, useMemo, useReducer, useImperativeHandle } from './hooks';\nexport memo from './memo';\nexport Fragment from './fragment';\nexport render from './render';\nexport Component, { PureComponent } from './vdom/component';\nexport version from './version';\n\nimport Host from './vdom/host';\nimport Instance from './vdom/instance';\nimport Element from './vdom/element';\nimport flattenChildren from './vdom/flattenChildren';\nimport DevtoolsHook from './devtools/index';\n\nexport const shared = {\n  Host,\n  Instance,\n  Element,\n  flattenChildren,\n};\n\nif (process.env.NODE_ENV !== 'production') {\n  /* global __RAX_DEVTOOLS_GLOBAL_HOOK__ */\n  if (typeof __RAX_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&\n    typeof __RAX_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {\n    __RAX_DEVTOOLS_GLOBAL_HOOK__.inject(DevtoolsHook);\n  }\n\n  if (typeof window !== 'undefined') {\n    if (window.__RAX_INITIALISED__) {\n      console.error('Warning: more than one instance of Rax has been initialised, this could lead to unexpected behaviour.');\n    }\n    window.__RAX_INITIALISED__ = true;\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/invokeFunctionsWithContext.js",
    "content": "export default function invokeFunctionsWithContext(fns, context, value) {\n  for (let i = 0, l = fns && fns.length; i < l; i++) {\n    fns[i].call(context, value);\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/memo.js",
    "content": "import shallowEqual from './vdom/shallowEqual';\n\nexport default function memo(type, compare) {\n  compare = compare || shallowEqual;\n\n  // Memo could composed\n  if (type.__compares) {\n    type.__compares.push(compare);\n  } else {\n    type.__compares = [compare];\n  }\n\n  return type;\n}\n"
  },
  {
    "path": "packages/rax/src/render.js",
    "content": "import injectRenderOptions from './vdom/injectRenderOptions';\nimport Instance from './vdom/instance';\nimport { isFunction, EMPTY_OBJECT } from './types';\nimport inject from './vdom/inject';\n\n// Inject init options to host, avoid circle deps between class component file and ./vdom/host\ninject();\n\nfunction render(element, container, options, callback) {\n  // Compatible with `render(element, container, callback)`\n  if (isFunction(options)) {\n    callback = options;\n    options = null;\n  }\n\n  options = options || EMPTY_OBJECT;\n  // Init inject\n  injectRenderOptions(options);\n\n  let rootComponent = Instance.mount(element, container, options);\n  let componentInstance = rootComponent.__getPublicInstance();\n\n  if (callback) {\n    callback.call(componentInstance);\n  }\n\n  return componentInstance;\n}\n\nexport default render;\n"
  },
  {
    "path": "packages/rax/src/toArray.js",
    "content": "import { isArray } from './types';\n\nexport default function toArray(obj) {\n  return isArray(obj) ? obj : [obj];\n}\n"
  },
  {
    "path": "packages/rax/src/types.js",
    "content": "export function isNull(obj) {\n  return obj === null;\n}\n\nexport function isFunction(obj) {\n  return typeof obj === 'function';\n}\n\nexport function isObject(obj) {\n  return typeof obj === 'object';\n}\n\nexport function isPlainObject(obj) {\n  return EMPTY_OBJECT.toString.call(obj) === '[object Object]';\n}\n\nexport function isArray(array) {\n  return Array.isArray(array);\n}\n\nexport function isString(string) {\n  return typeof string === 'string';\n}\n\nexport function isNumber(string) {\n  return typeof string === 'number';\n}\n\nexport function isFalsy(val) {\n  return !Boolean(val);\n}\n\nexport const NOOP = () => {};\nexport const EMPTY_OBJECT = {};\n"
  },
  {
    "path": "packages/rax/src/validateChildKeys.js",
    "content": "import Host from './vdom/host';\nimport { warning } from './error';\nimport { isArray } from './types';\n\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\nconst ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  let info = '';\n\n  const ownerComponent = Host.owner;\n  if (ownerComponent) {\n    const name = ownerComponent.__getName();\n    if (name) {\n      info = ` Check the render method of <${name}>.`;\n    }\n  }\n\n  if (!info) {\n    const parentName =\n      typeof parentType === 'string'\n        ? parentType\n        : parentType.displayName || parentType.name;\n    if (parentName) {\n      info = ` Check the top-level render call using <${parentName}>.`;\n    }\n  }\n  return info;\n}\n\nfunction isValidElement(object) {\n  return typeof object === 'object' && object !== null && object.type && !!object.props;\n}\n\nfunction validateExplicitKey(element, parentType) {\n  if (element.__validated || element.key != null) {\n    return;\n  }\n\n  element.__validated = true;\n\n  const currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n  if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n    return;\n  }\n  ownerHasKeyUseWarning[currentComponentErrorInfo] = true;\n\n  // Usually the current owner is the offender, but if it accepts children as a\n  // property, it may be the creator of the child that's responsible for\n  // assigning it a key.\n  let childOwner = '';\n  if (\n    element &&\n    element._owner &&\n    element._owner !== Host.owner\n  ) {\n    // Give the component that originally created this child.\n    childOwner = ` It was passed a child from <${element._owner.__getName()}>.`;\n  }\n\n  warning(`Each child in a list should have a unique \"key\" prop.${currentComponentErrorInfo}${childOwner}`);\n}\n\nexport default function validateChildKeys(node, parentType) {\n  // Only array or element object is valid child\n  if (typeof node !== 'object') {\n    return;\n  }\n\n  if (isArray(node)) {\n    for (let i = 0; i < node.length; i++) {\n      const child = node[i];\n      if (isValidElement(child)) {\n        validateExplicitKey(child, parentType);\n      }\n    }\n  } else if (isValidElement(node)) {\n    node.__validated = true;\n  }\n  // Rax don't support iterator object as element children\n  // TODO: add validate when rax support iterator object as element.\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/component.js",
    "content": "/* @jsx createElement */\n\nimport Component from '../component';\nimport createElement from '../../createElement';\n\ndescribe('Component', () => {\n  it('preserves the name of the class', () => {\n    class Foo extends Component { }\n    expect(Foo.name).toBe('Foo');\n  });\n\n  it('check a component is class type', () => {\n    class Foo extends Component { }\n    let foo = new Foo();\n    expect(foo.setState).toBeDefined();\n    expect(foo.forceUpdate).toBeDefined();\n  });\n\n  it('create a component with prop', () => {\n    class Foo extends Component {\n      render() {\n        return null;\n      }\n    }\n\n    let bar = () => {};\n    let foo = <Foo foo=\"Foo\" bar={bar} />;\n    expect(foo.props.foo).toBe('Foo');\n    expect(foo.props.bar).toBe(bar);\n  });\n\n  it('create a component with ignored prop', () => {\n    class Foo extends Component {\n      render() {\n        return null;\n      }\n    }\n\n    expect(() => {\n      let foo = <Foo key=\"key\" ref=\"ref\" />;\n      expect(foo.props.key).toBe(undefined);\n      expect(foo.props.ref).toBe(undefined);\n    }).toWarnDev('Adding a string ref \"ref\" that was not created inside render method, or multiple copies of Rax are used.', {withoutStack: true});\n  });\n\n  it('create a component based on state using initial values in this.props', function() {\n    class Foo extends Component {\n      constructor(props) {\n        super(props);\n        this.state = {bar: this.props.initialValue};\n      }\n      render() {\n        return null;\n      }\n    }\n\n    let foo = <Foo initialValue=\"Foo\" />;\n    let ElementType = foo.type;\n    let instance = new ElementType(foo.props);\n    expect(instance.state.bar).toBe('Foo');\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/composite.js",
    "content": "/* @jsx createElement */\n\nimport Component from '../component';\nimport createElement from '../../createElement';\nimport Host from '../host';\nimport render from '../../render';\nimport ServerDriver from 'driver-server';\n\ndescribe('CompositeComponent', function() {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('should rewire refs when rendering to different child types', function() {\n    class MyComponent extends Component {\n      state = {activated: false};\n\n      toggleActivatedState = () => {\n        this.setState({activated: !this.state.activated});\n      };\n\n      render() {\n        return !this.state.activated ?\n          <a ref=\"x\" /> :\n          <b ref=\"x\" />;\n      }\n    }\n\n    let component = render(<MyComponent />);\n    expect(component.refs.x.tagName).toBe('A');\n\n    component.toggleActivatedState();\n\n    jest.runAllTimers();\n    expect(component.refs.x.tagName).toBe('B');\n  });\n\n  it('donot call render when setState in componentWillMount', function() {\n    let container = createNodeElement('div');\n    let renderCounter = 0;\n    class Foo extends Component {\n      constructor() {\n        super();\n        this.state = {};\n      }\n      componentWillMount() {\n        this.setState({\n          value: 'foo'\n        });\n      }\n      render() {\n        ++renderCounter;\n        return <span className={this.state.value} />;\n      }\n    }\n\n    render(<Foo />, container);\n    expect(renderCounter).toEqual(1);\n    expect(container.childNodes[0].attributes.class).toBe('foo');\n  });\n\n  it('setState callback triggered', function() {\n    let container = createNodeElement('div');\n    let triggered = false;\n    class Foo extends Component {\n      constructor() {\n        super();\n        this.state = {};\n      }\n      componentWillMount() {\n        this.setState({\n          value: 'foo'\n        }, () => {\n          triggered = true;\n        });\n      }\n      componentWillReceiveProps() {\n        this.setState({\n          value: 'foo'\n        }, () => {\n          triggered = true;\n        });\n      }\n      render() {\n        return <span className={this.state.value} />;\n      }\n    }\n\n    const instance = render(<Foo />, container);\n    expect(triggered).toBe(true);\n    triggered = false;\n    instance.setState({}, () => triggered = true);\n    jest.runAllTimers();\n    expect(triggered).toBe(true);\n    triggered = false;\n    render(<Foo />, container);\n    expect(triggered).toBe(true);\n  });\n\n\n  it('setState callback triggered in didMount or didUpdate should receive latest state', function() {\n    let container = createNodeElement('div');\n    const logs = [];\n    class Foo extends Component {\n      constructor() {\n        super();\n        this.state = {\n          count: 1\n        };\n      }\n      componentDidMount() {\n        // eslint-disable-next-line react/no-did-mount-set-state\n        this.setState({\n          count: 2\n        }, () => {\n          logs.push(this.state.count);\n        });\n      }\n      componentDidUpdate() {\n        if (this.state.count === 2) {\n          // eslint-disable-next-line react/no-did-update-set-state\n          this.setState({\n            count: 3\n          }, () => {\n            logs.push(this.state.count);\n          });\n        };\n      }\n      render() {\n        return <span className={this.state.value} />;\n      }\n    }\n\n    render(<Foo />, container);\n    jest.runAllTimers();\n    expect(logs).toEqual([2, 3]);\n  });\n\n  it('will call all the normal life cycle methods', function() {\n    var lifeCycles = [];\n    let container = createNodeElement('div');\n\n    class Foo extends Component {\n      constructor() {\n        super();\n        this.state = {};\n      }\n      componentWillMount() {\n        this.setState({value: 'foo'});\n        lifeCycles.push('will-mount');\n      }\n      componentDidMount() {\n        lifeCycles.push('did-mount');\n      }\n      componentWillReceiveProps(nextProps) {\n        this.setState({value: 'bar'}, function() {\n          lifeCycles.push('receive-props-callback');\n        });\n        lifeCycles.push('receive-props', nextProps);\n      }\n      shouldComponentUpdate(nextProps, nextState) {\n        lifeCycles.push('should-update', nextProps, nextState);\n        return true;\n      }\n      componentWillUpdate(nextProps, nextState) {\n        lifeCycles.push('will-update', nextProps, nextState);\n      }\n      componentDidUpdate(prevProps, prevState) {\n        lifeCycles.push('did-update', prevProps, prevState);\n      }\n      componentWillUnmount() {\n        lifeCycles.push('will-unmount');\n      }\n      render() {\n        lifeCycles.push('render');\n        return <span className={this.props.value} />;\n      }\n    }\n\n    render(<div><Foo value=\"foo\" /></div>, container);\n    expect(lifeCycles).toEqual([\n      'will-mount',\n      'render',\n      'did-mount'\n    ]);\n    lifeCycles = []; // reset\n    render(<div><Foo value=\"bar\" /></div>, container);\n    expect(lifeCycles).toEqual([\n      'receive-props', {value: 'bar'},\n      'should-update', {value: 'bar'}, {value: 'bar'},\n      'will-update', {value: 'bar'}, {value: 'bar'},\n      'render',\n      'did-update', {value: 'foo'}, {value: 'foo'},\n      'receive-props-callback'\n    ]);\n    lifeCycles = []; // reset\n    render(<div />, container);\n    expect(lifeCycles).toEqual([\n      'will-unmount',\n    ]);\n  });\n\n  it('not break other component render when one component rise an error', () => {\n    let container = createNodeElement('div');\n    class MyComponent extends Component {\n      render() {\n        return [\n          <BrokenRender key=\"a\" />,\n          <NoBrokenRender key=\"b\" />\n        ];\n      }\n    }\n\n    class BrokenRender extends Component {\n      constructor() {\n        throw new Error('Hello');\n      }\n      render() {\n        return (\n          <span>Hello 1</span>\n        );\n      }\n    }\n\n    class NoBrokenRender extends Component {\n      render() {\n        return (\n          <span>Hello 2</span>\n        );\n      }\n    }\n\n    expect(() => {\n      render(<MyComponent />, container);\n      jest.runAllTimers();\n    }).toThrowError(/Hello/);\n\n    expect(container.childNodes[0].childNodes[0].data).toBe('Hello 2');\n  });\n\n  it('catches render error in a boundary', () => {\n    let container = createNodeElement('div');\n    class ErrorBoundary extends Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return (\n            <span>{`Caught an error: ${this.state.error.message}.`}</span>\n          );\n        }\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender(props) {\n      throw new Error('Hello');\n    }\n\n    render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>, container);\n\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toBe('Caught an error: Hello.');\n  });\n\n  it('catches component update error in a boundary', () => {\n    let container = createNodeElement('div');\n    class ErrorBoundary extends Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return (\n            <span>{`Caught an error: ${this.state.error.message}.`}</span>\n          );\n        }\n        return this.props.children;\n      }\n    }\n\n    class BrokenRender extends Component {\n      state = {foo: 'Hello'};\n      componentDidMount() {\n        setTimeout(() => {\n          this.setState({\n            foo: 'error'\n          });\n        });\n      }\n      render() {\n        if (this.state.foo === 'error') {\n          throw Error('foo');\n        }\n        return (\n          <span>{this.state.foo}</span>\n        );\n      }\n    }\n\n    render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>, container);\n\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toContain('Caught an error: foo');\n  });\n\n  it('catches lifeCycles errors in a boundary', () => {\n    let container = createNodeElement('div');\n    class ErrorBoundary extends Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return (\n            <span>{`Caught an error: ${this.state.error.message}.`}</span>\n          );\n        }\n        return this.props.children;\n      }\n    }\n\n    class BrokenRender extends Component {\n      componentDidMount() {\n        throw new Error('Hello');\n      }\n      render() {\n        return (\n          <span>Hello</span>\n        );\n      }\n    }\n\n    render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toBe('Caught an error: Hello.');\n  });\n\n  it('catches constructor errors in a boundary', () => {\n    let container = createNodeElement('div');\n    class ErrorBoundary extends Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return (\n            <span>{`Caught an error: ${this.state.error.message}.`}</span>\n          );\n        }\n        return this.props.children;\n      }\n    }\n\n    class BrokenRender extends Component {\n      constructor() {\n        throw new Error('Hello');\n      }\n      render() {\n        return (\n          <span>Hello</span>\n        );\n      }\n    }\n\n    render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toBe('Caught an error: Hello.');\n  });\n\n  it('catches render errors in a component', () => {\n    let container = createNodeElement('div');\n    class BrokenRender extends Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return (\n            <span>{`Caught an error: ${this.state.error.message}.`}</span>\n          );\n        }\n        throw new Error('Hello');\n      }\n    }\n\n    render(<BrokenRender />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toBe('Caught an error: Hello.');\n  });\n\n  it('should not attempt to recover an unmounting error boundary', () => {\n    let container = createNodeElement('div');\n    let logs = [];\n    class Parent extends Component {\n      componentWillUnmount() {\n        logs.push('Parent componentWillUnmount');\n      }\n      render() {\n        return <Boundary />;\n      }\n    }\n\n    class Boundary extends Component {\n      componentDidCatch(e) {\n        logs.push(`Caught error: ${e.message}`);\n      }\n      render() {\n        return <ThrowsOnUnmount />;\n      }\n    }\n\n    class ThrowsOnUnmount extends Component {\n      componentWillUnmount() {\n        logs.push('ThrowsOnUnmount componentWillUnmount');\n        throw new Error('unmount error');\n      }\n      render() {\n        return null;\n      }\n    }\n\n    render(<Parent />, container);\n    render(<div />, container);\n    expect(logs).toEqual([\n      // Parent unmounts before the error is thrown.\n      'Parent componentWillUnmount',\n      'ThrowsOnUnmount componentWillUnmount',\n    ]);\n  });\n\n  it('rendering correct on siblings of a component that throws', () => {\n    let container = createNodeElement('div');\n    function BrokenRender() {\n      throw new Error('Hello');\n    }\n    class ErrorBoundary extends Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return (\n            <div>{`Caught an error: ${this.state.error.message}.`}</div>\n          );\n        }\n        return (\n          <div>\n            <span>siblings</span>\n            <BrokenRender />\n            <span>siblings</span>\n          </div>\n        );\n      }\n    }\n\n    render(<ErrorBoundary />, container);\n    jest.runAllTimers();\n    expect(container.childNodes.length).toBe(1);\n    expect(container.childNodes[0].childNodes[0].data).toBe('Caught an error: Hello.');\n  });\n\n  it('working correct with fragment when a component that throw error', () => {\n    let container = createNodeElement('div');\n    class ErrorBoundary extends Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return (\n            <span>{`Caught an error: ${this.state.error.message}.`}</span>\n          );\n        }\n        return [\n          <span key={'1'}>siblings</span>,\n          <BrokenRender key={'error'} />,\n          <span key={'2'}>siblings</span>\n        ];\n      }\n    }\n\n    function BrokenRender() {\n      throw new Error('Hello');\n    }\n\n    render(<ErrorBoundary />, container);\n    jest.runAllTimers();\n    expect(container.childNodes.length).toBe(1);\n    expect(container.childNodes[0].childNodes[0].data).toBe('Caught an error: Hello.');\n  });\n\n  it('Life cycle method invocation sequence should be correct', () => {\n    let logs = [];\n\n    let container = createNodeElement('div');\n    class ErrorBoundary extends Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      componentDidMount() {\n        logs.push('componentDidMountErrorBoundary');\n      }\n      componentDidUpdate() {\n        logs.push('componentDidUpdateErrorBoundary');\n      }\n      render() {\n        if (this.state.error) {\n          return (\n            <span>{`Caught an error: ${this.state.error.message}.`}</span>\n          );\n        }\n        return this.props.children;\n      }\n    }\n\n    class Life1 extends Component {\n      componentWillMount() {\n        logs.push('componentWillMount1');\n      }\n      render() {\n        logs.push('render1');\n        return null;\n      }\n      componentDidMount() {\n        logs.push('componentDidMount1');\n      }\n\n      componentWillUpdate() {\n        logs.push('componentWillUpdata1');\n      }\n      componentDidUpdate() {\n        logs.push('componentDidUpdate1');\n      }\n      componentWillUnmount() {\n        logs.push('componentWillUnmount1');\n      }\n    }\n\n    class Life2 extends Component {\n      componentWillMount() {\n        logs.push('componentWillMount2');\n      }\n      render() {\n        logs.push('render2');\n        throw new Error();\n      }\n      componentDidMount() {\n        logs.push('componentDidMount2');\n      }\n      componentWillUpdate() {\n        logs.push('componentWillUpdate2');\n      }\n      componentDidUpdate() {\n        logs.push('componentDidUpdate2');\n      }\n      componentWillUnmount() {\n        logs.push('componentWillUnmount2');\n      }\n    }\n\n    class Life3 extends Component {\n      componentWillMount() {\n        logs.push('componentWillMount3');\n      }\n      render() {\n        logs.push('render3');\n        return null;\n      }\n      componentDidMount() {\n        logs.push('componentDidMount3');\n      }\n      componentWillUpdata() {\n        logs.push('componentWillUpdata3');\n      }\n      componentDidUpdate() {\n        logs.push('componentDidUpdate3');\n      }\n      componentWillUnmount() {\n        logs.push('componentWillUnmount3');\n      }\n    }\n\n    render(\n      <ErrorBoundary>\n        <Life1 />\n        <Life2 />\n        <Life3 />\n      </ErrorBoundary>, container);\n\n    jest.runAllTimers();\n    expect(logs).toEqual([\n      'componentWillMount1',\n      'render1',\n      'componentWillMount2',\n      'render2',\n      'componentWillMount3',\n      'render3',\n      'componentDidMount1',\n      'componentDidMount2',\n      'componentDidMount3',\n      'componentDidMountErrorBoundary',\n      'componentWillUnmount1',\n      'componentWillUnmount2',\n      'componentWillUnmount3',\n      'componentDidUpdateErrorBoundary'\n    ]);\n  });\n\n  it('should boundary exec componentDidCatch when child setState throw error', () => {\n    let container = createNodeElement('div');\n    let child;\n\n    class Child extends Component {\n      state = {\n        count: 1\n      }\n      render() {\n        child = this;\n        if (this.state.count === 2) {\n          throw new Error('Hello');\n        }\n        return (\n          <span>Hello</span>\n        );\n      }\n    }\n\n    class ErrorBoundary extends Component {\n      state = {error: null};\n      componentDidCatch(error) {\n        this.setState({error});\n      }\n      render() {\n        if (this.state.error) {\n          return (\n            <div>{`Caught an error: ${this.state.error.message}.`}</div>\n          );\n        }\n        return (\n          <div>\n            <Child />\n          </div>\n        );\n      }\n    }\n\n    render(<ErrorBoundary><Child /></ErrorBoundary>, container);\n    expect(container.childNodes[0].childNodes[0].childNodes[0].data).toBe('Hello');\n    child.setState({count: 2});\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toBe('Caught an error: Hello.');\n  });\n\n  it('should update state to the next render when catch error.', () => {\n    let container = createNodeElement('div');\n    class ErrorBoundary extends Component {\n      constructor(props) {\n        super(props);\n        this.state = { hasError: false };\n      }\n\n      static getDerivedStateFromError(error) {\n        return { hasError: true };\n      }\n\n      componentDidCatch(error, errorInfo) {\n        // log\n      }\n\n      render() {\n        if (this.state.hasError) {\n          return <h1>Something went wrong.</h1>;\n        }\n\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender(props) {\n      throw new Error('Hello');\n    }\n\n    render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>, container);\n\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toBe('Something went wrong.');\n  });\n\n  it('should catch error only with getDerivedStateFromError.', () => {\n    let container = createNodeElement('div');\n    class ErrorBoundary extends Component {\n      constructor(props) {\n        super(props);\n        this.state = { hasError: false };\n      }\n\n      static getDerivedStateFromError(error) {\n        return { hasError: true };\n      }\n\n      render() {\n        if (this.state.hasError) {\n          return <h1>Something went wrong.</h1>;\n        }\n\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender(props) {\n      throw new Error('Hello');\n    }\n\n    render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>, container);\n\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toBe('Something went wrong.');\n  });\n\n  it('should catch the exact error with getDerivedStateFromError.', () => {\n    let caughtError;\n    let exampleError = new Error('Example error message');\n    let container = createNodeElement('div');\n\n    class ErrorBoundary extends Component {\n      constructor(props) {\n        super(props);\n        this.state = { hasError: false, error: null };\n      }\n\n      static getDerivedStateFromError(error) {\n        caughtError = error;\n        return { hasError: true, error };\n      }\n\n      render() {\n        if (this.state.hasError) {\n          return <h1>{this.state.error.message}</h1>;\n        }\n\n        return this.props.children;\n      }\n    }\n\n    function BrokenRender(props) {\n      throw exampleError;\n    }\n\n    render(\n      <ErrorBoundary>\n        <BrokenRender />\n      </ErrorBoundary>, container);\n\n    jest.runAllTimers();\n\n    expect(caughtError).toBe(exampleError);\n    expect(container.childNodes[0].childNodes[0].data).toBe('Example error message');\n  });\n\n  it('should render correct when prevRenderedComponent did not generate nodes', () => {\n    let container = createNodeElement('div');\n    class Frag extends Component {\n      render() {\n        return [];\n      }\n    }\n    class App extends Component {\n      state = {count: 0};\n      render() {\n        if (this.state.count === 0) {\n          return <Frag />;\n        }\n        return <div />;\n      }\n    }\n\n    const instance = render(<App />, container);\n    expect(container.childNodes.length).toBe(0);\n    instance.setState({count: 1});\n    jest.runAllTimers();\n    expect(container.childNodes[0].tagName).toBe('DIV');\n  });\n\n  it('render component that componentDidMount could get mounted DOM', () => {\n    let container = createNodeElement('div');\n    class Child extends Component {\n      componentDidMount() {\n        expect(container.childNodes[0].childNodes[0].childNodes[0].tagName).toBe('DIV');\n      }\n      render() {\n        return <div />;\n      }\n    }\n    class App extends Component {\n      render() {\n        return <div><Child /></div>;\n      }\n    }\n\n    const instance = render(<div><App /></div>, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].tagName).toBe('DIV');\n  });\n\n  it('render with fragment that componentDidMount could get mounted DOM', () => {\n    let container = createNodeElement('div');\n    class Child extends Component {\n      componentDidMount() {\n        expect(container.childNodes[0].tagName).toBe('DIV');\n      }\n      render() {\n        return <div />;\n      }\n    }\n    class App extends Component {\n      render() {\n        return [\n          <Child key=\"1\" />\n        ];\n      }\n    }\n\n    const instance = render(<App />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].tagName).toBe('DIV');\n  });\n\n  it('schedules sync updates when inside componentDidMount/Update', () => {\n    let container = createNodeElement('div');\n    let instance;\n    let ops = [];\n\n    class Foo extends Component {\n      state = {tick: 0};\n\n      componentDidMount() {\n        ops.push('componentDidMount (before setState): ' + this.state.tick);\n        this.setState({tick: 1}); // eslint-disable-line\n        // We're in a batch. Update hasn't flushed yet.\n        ops.push('componentDidMount (after setState): ' + this.state.tick);\n      }\n\n      componentDidUpdate() {\n        ops.push('componentDidUpdate: ' + this.state.tick);\n        if (this.state.tick === 2) {\n          ops.push('componentDidUpdate (before setState): ' + this.state.tick);\n          this.setState({tick: 3}); // eslint-disable-line\n          ops.push('componentDidUpdate (after setState): ' + this.state.tick);\n          // We're in a batch. Update hasn't flushed yet.\n        }\n      }\n\n      render() {\n        ops.push('render: ' + this.state.tick);\n        instance = this;\n        return <span prop={this.state.tick} />;\n      }\n    }\n\n    render(<Foo />, container);\n\n    jest.runAllTimers();\n    expect(ops).toEqual([\n      'render: 0',\n      'componentDidMount (before setState): 0',\n      'componentDidMount (after setState): 0',\n      // If the setState inside componentDidMount were deferred, there would be\n      // no more ops. Because it has Task priority, we get these ops, too:\n      'render: 1',\n      'componentDidUpdate: 1',\n    ]);\n\n    ops = [];\n    instance.setState({tick: 2});\n    jest.runAllTimers();\n    expect(ops).toEqual([\n      'render: 2',\n      'componentDidUpdate: 2',\n      'componentDidUpdate (before setState): 2',\n      'componentDidUpdate (after setState): 2',\n      // If the setState inside componentDidUpdate were deferred, there would be\n      // no more ops. Because it has Task priority, we get these ops, too:\n      'render: 3',\n      'componentDidUpdate: 3',\n    ]);\n  });\n\n  it('performs Task work in the callback', () => {\n    let container = createNodeElement('div');\n    class Foo extends Component {\n      state = {step: 1};\n      componentDidMount() {\n        this.setState({step: 2}, () => { // eslint-disable-line\n          this.setState({step: 3}, () => {\n            this.setState({step: 4}, () => {\n              this.setState({step: 5});\n            });\n          });\n        });\n      }\n      render() {\n        return <span>{this.state.step}</span>;\n      }\n    }\n    render(<Foo />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toBe('5');\n  });\n\n  it('should batch child/parent state updates together', () => {\n    let container = createNodeElement('div');\n    let container2 = createNodeElement('div');\n\n    var parentUpdateCount = 0;\n\n    class Parent extends Component {\n      state = {x: 0};\n\n      componentDidUpdate() {\n        parentUpdateCount++;\n      }\n\n      render() {\n        return <div><Child ref=\"child\" x={this.state.x} /><Child2 ref=\"child2\" x={this.state.x} /></div>;\n      }\n    }\n\n    var childUpdateCount = 0;\n\n    class Child extends Component {\n      state = {y: 0};\n\n      componentDidUpdate() {\n        childUpdateCount++;\n      }\n\n      render() {\n        return <div>{this.props.x + this.state.y}</div>;\n      }\n    }\n\n    var child2UpdateCount = 0;\n\n    class Child2 extends Component {\n      state = {y: 0};\n\n      componentDidUpdate() {\n        child2UpdateCount++;\n      }\n\n      render() {\n        return <div>{this.props.x + this.state.y}</div>;\n      }\n    }\n\n    var instance = render(<Parent />, container);\n    var child = instance.refs.child;\n    var child2 = instance.refs.child2;\n    expect(instance.state.x).toBe(0);\n    expect(child.state.y).toBe(0);\n    expect(child2.state.y).toBe(0);\n\n    function Batch() {\n      child.setState({y: 2});\n      instance.setState({x: 1});\n      child2.setState({y: 2});\n      expect(instance.state.x).toBe(0);\n      expect(child.state.y).toBe(0);\n      expect(child2.state.y).toBe(0);\n      expect(parentUpdateCount).toBe(0);\n      expect(childUpdateCount).toBe(0);\n      expect(child2UpdateCount).toBe(0);\n      return null;\n    }\n\n    render(<Batch />, container2);\n    jest.runAllTimers();\n    expect(instance.state.x).toBe(1);\n    expect(child.state.y).toBe(2);\n    expect(child2.state.y).toBe(2);\n    expect(parentUpdateCount).toBe(1);\n\n    // Batching reduces the number of updates here to 1.\n    expect(childUpdateCount).toBe(1);\n    expect(child2UpdateCount).toBe(1);\n  });\n\n  it('does not call render after a component as been deleted', () => {\n    let container = createNodeElement('div');\n    let container2 = createNodeElement('div');\n    var renderCount = 0;\n    var componentB = null;\n\n    class B extends Component {\n      state = {updates: 0};\n\n      componentDidMount() {\n        componentB = this;\n      }\n\n      render() {\n        renderCount++;\n        return <div />;\n      }\n    }\n\n    class A extends Component {\n      state = {showB: true};\n\n      render() {\n        return this.state.showB ? <B /> : <div />;\n      }\n    }\n\n    var component = render(<A />, container);\n    function Batch() {\n      // B will have scheduled an update but the batching should ensure that its\n      // update never fires.\n      componentB.setState({updates: 1});\n      component.setState({showB: false});\n    }\n\n    render(<Batch />, container2);\n    expect(renderCount).toBe(1);\n  });\n\n  it('does not update one component twice when schedule in the rendering phase', () => {\n    let container = createNodeElement('div');\n    let logs = [];\n\n    class Child extends Component {\n      state = {\n        count: 0\n      };\n      componentDidUpdate() {\n        logs.push(this.props.child);\n      }\n      componentDidMount() {\n        this.setState({count: 1}); // eslint-disable-line\n        this.setState({count: 2}); // eslint-disable-line\n        this.setState({count: 3}); // eslint-disable-line\n      }\n      render() {\n        return (\n          [\n            <span key={'1'}>{this.props.count}</span>,\n            <span key={'2'}>{this.state.count}</span>\n          ]\n        );\n      }\n    }\n\n    class Parent1 extends Component {\n      state = {\n        count: 0\n      }\n      componentDidUpdate() {\n        logs.push('Parent1');\n      }\n      componentDidMount() {\n        this.setState({count: 1}); // eslint-disable-line\n        this.setState({count: 2}); // eslint-disable-line\n      }\n      render() {\n        return <Child count={this.state.count} child=\"Child1\" />;\n      }\n    }\n\n    class Parent2 extends Component {\n      state = {\n        count: 0\n      }\n      shouldComponentUpdate() {\n        return false;\n      }\n      componentDidUpdate() {\n        logs.push('Parent2');\n      }\n      componentDidMount() {\n        this.setState({count: 1}); // eslint-disable-line\n        this.setState({count: 2}); // eslint-disable-line\n      }\n      render() {\n        return <Child count={this.state.count} child=\"Child2\" />;\n      }\n    }\n\n    class App extends Component {\n      render() {\n        return [<Parent1 key={'a'} />, <Parent2 key={'b'} />];\n      }\n    }\n    render(<App />, container);\n    jest.runAllTimers();\n    // Child1  Child2 appears only once\n    expect(logs).toEqual(['Child1', 'Parent1', 'Child2']);\n    expect(container.childNodes[0].childNodes[0].data).toBe('2');\n    expect(container.childNodes[1].childNodes[0].data).toBe('3');\n    expect(container.childNodes[2].childNodes[0].data).toBe('0');\n    expect(container.childNodes[3].childNodes[0].data).toBe('3');\n  });\n\n  it('should update fragment to right position', function() {\n    let el = createNodeElement('div');\n    class Hello1 extends Component {\n      render() {\n        if (this.props.show) {\n          return 'hello1';\n        }\n        return null;\n      }\n    }\n\n    class Text extends Component {\n      render() {\n        return this.props.children;\n      }\n    }\n\n    class Hello2 extends Component {\n      render() {\n        if (this.props.show) {\n          return [<Text key=\"1\">1</Text>, <Text key=\"2\">2</Text>, <Text key=\"3\">3</Text>];\n        } else {\n          return [<Text key=\"1\">1</Text>, <Text key=\"2\">2</Text>];\n        }\n      }\n    }\n\n    class MyComponent extends Component {\n      state = {\n        show: false\n      }\n      render() {\n        return (\n          <div>\n            {'foo'}\n            <Hello1 show={this.state.show} />\n            <Hello2 show={this.state.show} />\n          </div>\n        );\n      }\n    }\n\n    let inst = render(<MyComponent />, el);\n\n    let container = el.childNodes[0];\n    let childNodes = container.childNodes;\n    expect(childNodes.length).toBe(4);\n    expect(childNodes[0].data).toBe('foo');\n    expect(childNodes[1].data).toBe(' empty ');\n    expect(childNodes[2].data).toBe('1');\n    expect(childNodes[3].data).toBe('2');\n\n    inst.setState({\n      show: true\n    });\n    jest.runAllTimers();\n\n    childNodes = container.childNodes;\n\n    expect(childNodes.length).toBe(5);\n    expect(childNodes[0].data).toBe('foo');\n    expect(childNodes[1].data).toBe('hello1');\n    expect(childNodes[2].data).toBe('1');\n    expect(childNodes[3].data).toBe('2');\n    expect(childNodes[4].data).toBe('3');\n  });\n\n  it('unmount dirty component', function() {\n    let el = createNodeElement('div');\n    let childInstance1 = null;\n    let childInstance2 = null;\n\n    class Child1 extends Component {\n      render() {\n        childInstance1 = this;\n        return <div>child1</div>;\n      }\n    }\n\n    class Child2 extends Component {\n      render() {\n        childInstance2 = this;\n        return <div>child2</div>;\n      }\n    }\n\n    class App extends Component {\n      componentWillReceiveProps() {\n        childInstance1.forceUpdate();\n        childInstance2.forceUpdate();\n      }\n\n      render() {\n        if (this.props.empty) return null;\n        return [<Child1 key=\"1\" />, <Child2 key=\"2\" />];\n      }\n    }\n    render(<App />, el);\n    expect(el.childNodes[0].childNodes[0].data).toBe('child1');\n    expect(el.childNodes[1].childNodes[0].data).toBe('child2');\n    render(<App empty />, el);\n    jest.runAllTimers();\n    expect(el.childNodes[0].nodeType).toEqual(8);\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/context.js",
    "content": "'use strict';\n\nimport Component from '../component';\nimport PropTypes from 'prop-types';\nimport createElement from '../../createElement';\nimport Host from '../host';\nimport render from '../../render';\nimport { flush } from '../scheduler';\nimport ServerDriver from 'driver-server';\n\ndescribe('Context', function() {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('should pass context when rendering subtree elsewhere', function() {\n    let container = createNodeElement('div');\n\n    class MyComponent extends Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      render() {\n        return <div>{this.context.foo}</div>;\n      }\n    }\n\n    class Parent extends Component {\n      static childContextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      getChildContext() {\n        return {\n          foo: 'bar',\n        };\n      }\n\n      render() {\n        return <MyComponent />;\n      }\n    }\n\n    render(<Parent />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('bar');\n  });\n\n  it('should filter out context not in contextTypes', function() {\n    class MyComponent extends Component {\n      static contextTypes = {\n        foo: PropTypes.string,\n      };\n\n      render() {\n        return <div />;\n      }\n    }\n\n    class ComponentInFooBarContext extends Component {\n      static childContextTypes = {\n        foo: PropTypes.string,\n        bar: PropTypes.number,\n      };\n\n      getChildContext() {\n        return {\n          foo: 'abc',\n          bar: 123,\n        };\n      }\n\n      render() {\n        return <MyComponent />;\n      }\n    }\n\n    let instance = render(<ComponentInFooBarContext />);\n    expect(instance._internal._renderedComponent._instance.context).toEqual({foo: 'abc'});\n  });\n\n  it('should update context if it changes due to setState', function() {\n    var container = createNodeElement('div');\n\n    class MyComponent extends Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n        getFoo: PropTypes.func.isRequired,\n      };\n\n      render() {\n        return <div>{this.context.foo + '-' + this.context.getFoo()}</div>;\n      }\n    }\n\n    class Parent extends Component {\n      static childContextTypes = {\n        foo: PropTypes.string.isRequired,\n        getFoo: PropTypes.func.isRequired,\n      };\n\n      state = {\n        bar: 'initial',\n      };\n\n      getChildContext() {\n        return {\n          foo: this.state.bar,\n          getFoo: () => this.state.bar,\n        };\n      }\n\n      render() {\n        return <MyComponent />;\n      }\n    }\n\n    var instance = render(<Parent />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('initial-initial');\n\n    instance.setState({bar: 'changed'});\n    jest.runAllTimers();\n\n    expect(container.childNodes[0].childNodes[0].data).toBe('changed-changed');\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/empty.js",
    "content": "/* @jsx createElement */\n\n'use strict';\n\nimport createElement from '../../createElement';\nimport Host from '../host';\nimport render from '../../render';\nimport ServerDriver from 'driver-server';\nimport { PureComponent } from '../component';\n\ndescribe('EmptyComponent', function() {\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  it('empty nodes should not be rebuilt', function() {\n    class Foo extends PureComponent {\n      state = {\n        alwaysShowNULL: false\n      };\n      render() {\n        return (\n          this.state.alwaysShowNULL ? null : null\n        );\n      }\n    }\n    const el = createNodeElement('div');\n    let component = render(<Foo />, el);\n    jest.runAllTimers();\n\n    component.setState({alwaysShowNULL: !component.state.alwaysShowNULL});\n    jest.runAllTimers();\n    const emptyNode1 = el.childNodes[0];\n\n    component.setState({alwaysShowNULL: !component.state.alwaysShowNULL});\n    jest.runAllTimers();\n    const emptyNode2 = el.childNodes[0];\n\n\n    expect(emptyNode1).toBe(emptyNode2);\n  });\n\n  it('empty node is updated normally', function() {\n    class Foo extends PureComponent {\n      state = {\n        alwaysShowNULL: true\n      };\n      render() {\n        return (\n          [\n            <div key=\"foo-div\"></div>,\n            this.state.alwaysShowNULL ? null : <label key=\"hello\" text=\"hello\" />,\n            <label key=\"world\" text=\"world\" />,\n          ]\n        );\n      }\n    }\n    const el = createNodeElement('div');\n    let component = render(<Foo />, el);\n    jest.runAllTimers();\n    expect(el.childNodes.length).toBe(3);\n    const originEmptyNode = el.childNodes[1];\n\n    component.setState({alwaysShowNULL: false});\n    jest.runAllTimers();\n    const emptyNode1 = el.childNodes[1];\n    expect(el.childNodes.length).toBe(3);\n    expect(originEmptyNode).not.toBe(emptyNode1);\n  });\n\n  it('empty node is created by falsy element should not be rebuilt', () => {\n    class Foo extends PureComponent {\n      state = {\n        alwaysShowUndefined: false\n      };\n      render() {\n        return (\n          this.state.alwaysShowUndefined ? undefined : undefined\n        );\n      }\n    }\n    const el = createNodeElement('div');\n    let component = render(<Foo />, el);\n    jest.runAllTimers();\n\n    component.setState({alwaysShowUndefined: !component.state.alwaysShowUndefined});\n    jest.runAllTimers();\n    const emptyNode1 = el.childNodes[0];\n\n    component.setState({alwaysShowUndefined: !component.state.alwaysShowUndefined});\n    jest.runAllTimers();\n    const emptyNode2 = el.childNodes[0];\n\n\n    expect(emptyNode1).toBe(emptyNode2);\n  });\n\n  it('empty node is created by falsy element should be replaced normally', () => {\n    class Foo extends PureComponent {\n      state = {\n        alwaysShowUndefined: false\n      };\n      render() {\n        return (\n          this.state.alwaysShowUndefined ? undefined : <label key=\"hello\" text=\"hello\" />\n        );\n      }\n    }\n    const el = createNodeElement('div');\n    let component = render(<Foo />, el);\n    jest.runAllTimers();\n    expect(el.childNodes.length).toBe(1);\n    const originEmptyNode = el.childNodes[0];\n\n    component.setState({\n      alwaysShowUndefined: true\n    });\n\n    jest.runAllTimers();\n    const emptyNode1 = el.childNodes[0];\n    expect(el.childNodes.length).toBe(1);\n    expect(originEmptyNode).not.toBe(emptyNode1);\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/fragment.js",
    "content": "/* @jsx createElement */\n\n'use strict';\n\nimport Component from '../component';\nimport createElement from '../../createElement';\nimport Host from '../host';\nimport render from '../../render';\nimport {INTERNAL, RENDERED_COMPONENT} from '../../constant';\nimport ServerDriver from 'driver-server';\n\ndescribe('FragmentComponent', function() {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('should updates a mounted text component in place', function() {\n    let el = createNodeElement('div');\n    let inst = render(['foo', 'bar'], el);\n\n    let foo = el.childNodes[0];\n    let bar = el.childNodes[1];\n    expect(foo.data).toBe('foo');\n    expect(bar.data).toBe('bar');\n  });\n\n  it('should diff update correct', function() {\n    let el = createNodeElement('div');\n    class Hello extends Component {\n      render() {\n        return [\n          <div key={'root'}>\n            <span>hello</span>\n            <span>{this.props.message}</span>\n          </div>\n        ];\n      }\n    }\n\n    let beforeInst = render(<Hello message=\"world\" />, el);\n    let beforeContainer = el.childNodes[0];\n    let beforeDiv = beforeContainer.childNodes[0];\n    let beforeSpan = beforeDiv.childNodes[0];\n\n    let inst = render(<Hello message=\"rax\" />, el);\n    let container = el.childNodes[0];\n    let div = container.childNodes[0];\n    let span = div.childNodes[0];\n\n    expect(beforeContainer).toBe(container);\n    expect(beforeDiv).toBe(div);\n    expect(beforeSpan).toBe(span);\n  });\n\n  it('should append to correct position', function() {\n    let el = createNodeElement('div');\n    class Hello1 extends Component {\n      render() {\n        return [\n          this.props.show ? 'hello1' : null,\n          this.props.show ? 'hello1' : null\n        ];\n      }\n    }\n\n    class Hello2 extends Component {\n      render() {\n        return [\n          this.props.show ? 'hello2' : null,\n          this.props.show ? 'hello2' : null\n        ];\n      }\n    }\n\n    class MyComponent extends Component {\n      state = {\n        show: false\n      }\n      render() {\n        return (\n          <div>\n            {'foo'}\n            <Hello1 show={this.state.show} />\n            <Hello2 show={this.state.show} />\n          </div>\n        );\n      }\n    }\n\n    let inst = render(<MyComponent />, el);\n\n    let container = el.childNodes[0];\n    let childNodes = container.childNodes;\n\n    expect(childNodes.length).toBe(5);\n    expect(childNodes[0].data).toBe('foo');\n    expect(childNodes[1].data).toBe(' empty ');\n    expect(childNodes[2].data).toBe(' empty ');\n    expect(childNodes[3].data).toBe(' empty ');\n    expect(childNodes[4].data).toBe(' empty ');\n\n    inst.setState({\n      show: true\n    });\n\n    jest.runAllTimers();\n\n    childNodes = container.childNodes;\n\n    expect(childNodes.length).toBe(5);\n    expect(childNodes[0].data).toBe('foo');\n    expect(childNodes[1].data).toBe('hello1');\n    expect(childNodes[2].data).toBe('hello1');\n    expect(childNodes[3].data).toBe('hello2');\n    expect(childNodes[4].data).toBe('hello2');\n  });\n\n  it('should update correct', function() {\n    let el = createNodeElement('div');\n\n    class Hello extends Component {\n      render() {\n        return [\n          <span key={'1'}>1</span>,\n          <span key={'2'}>2</span>\n        ];\n      }\n    }\n\n    class World extends Component {\n      render() {\n        return [\n          <span key={'3'}>3</span>,\n          <span key={'4'}>4</span>\n        ];\n      }\n    }\n\n    class MyComponent extends Component {\n      state = {\n        list: [<Hello key={'hello'} />]\n      }\n      componentDidMount() {\n        this.state.list.push(<World key={'world'} />);\n        /* eslint-disable */\n        this.setState(this.state);\n        /* eslint-enable */\n      }\n      render() {\n        return (\n          <div>\n            {this.state.list}\n          </div>\n        );\n      }\n    }\n\n    let inst = render(<MyComponent />, el);\n\n    let container = el.childNodes[0];\n    let childNodes = container.childNodes;\n    jest.runAllTimers();\n\n    expect(childNodes.length).toBe(4);\n    expect(childNodes[0].childNodes[0].data).toBe('1');\n    expect(childNodes[1].childNodes[0].data).toBe('2');\n    expect(childNodes[2].childNodes[0].data).toBe('3');\n    expect(childNodes[3].childNodes[0].data).toBe('4');\n  });\n\n  it('should render correct when switching from a single child', function() {\n    let el = createNodeElement('div');\n\n    class Hello extends Component {\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    class MyComponent extends Component {\n      render() {\n        let { condition } = this.props;\n        return condition ? <Hello key=\"a\" /> :\n          [<Hello key=\"a\" />, <div key=\"b\">World</div>];\n      }\n    }\n\n    let inst = render(<MyComponent />, el);\n    let childNodes = el.childNodes;\n\n    expect(childNodes.length).toBe(2);\n    expect(childNodes[0].childNodes[0].data).toBe('Hello');\n    expect(childNodes[1].childNodes[0].data).toBe('World');\n\n    inst = render(<MyComponent condition={true} />, el);\n    expect(childNodes.length).toBe(1);\n    expect(childNodes[0].childNodes[0].data).toBe('Hello');\n  });\n\n  it('should render correct when switching to a nested array', function() {\n    let el = createNodeElement('div');\n\n    class Hello extends Component {\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    class MyComponent extends Component {\n      render() {\n        let { condition } = this.props;\n        return condition ? <Hello key=\"a\" /> :\n          [[<Hello key=\"a\" />, <div key=\"b\">World</div>], <div key={'c'} />];\n      }\n    }\n\n    let inst = render(<MyComponent />, el);\n    let childNodes = el.childNodes;\n\n    expect(childNodes.length).toBe(3);\n    expect(childNodes[0].childNodes[0].data).toBe('Hello');\n    expect(childNodes[1].childNodes[0].data).toBe('World');\n    expect(childNodes[2].tagName).toBe('DIV');\n\n    inst = render(<MyComponent condition={true} />, el);\n    expect(childNodes.length).toBe(1);\n    expect(childNodes[0].childNodes[0].data).toBe('Hello');\n  });\n\n  it('should render correct if an implicit key slot switches from/to null', function() {\n    let el = createNodeElement('div');\n    let instance = null;\n\n    class Hello extends Component {\n      render() {\n        instance = this;\n        return <div>World</div>;\n      }\n    }\n\n    class MyComponent extends Component {\n      render() {\n        let { condition } = this.props;\n        return condition ? [null, <Hello key={'a'} />] :\n          [<div key={'b'}>Hello</div>, <Hello key={'c'} />];\n      }\n    }\n\n    let inst = render(<MyComponent />, el);\n    let childNodes = el.childNodes;\n\n    expect(childNodes.length).toBe(2);\n    expect(childNodes[0].childNodes[0].data).toBe('Hello');\n    expect(childNodes[1].childNodes[0].data).toBe('World');\n\n    let instanceA = instance;\n    expect(instanceA).not.toBe(null);\n\n    inst = render(<MyComponent condition={true} />, el);\n\n    expect(childNodes.length).toBe(2);\n    expect(childNodes[0].data).toBe(' empty ');\n    expect(childNodes[1].childNodes[0].data).toBe('World');\n\n    let instanceB = instance;\n    // expect(instanceB).toBe(instanceA);\n\n    inst = render(<MyComponent condition={false} />, el);\n\n    expect(childNodes.length).toBe(2);\n    expect(childNodes[0].childNodes[0].data).toBe('Hello');\n    expect(childNodes[1].childNodes[0].data).toBe('World');\n\n    let instanceC = instance;\n    // expect(instanceC === instanceA).toBe(true);\n  });\n\n  it('should render correct with nested array', function() {\n    let el = createNodeElement('div');\n\n    class Hello extends Component {\n      render() {\n        return <div>Hello</div>;\n      }\n    }\n\n    class MyComponent extends Component {\n      render() {\n        let { condition } = this.props;\n        return condition ? [[<div key=\"b\">World</div>, <Hello key=\"a\" />]] :\n          [[<Hello key=\"a\" />, <div key=\"b\">World</div>], <div key={'c'} />];\n      }\n    }\n\n    let inst = render(<MyComponent />, el);\n    let childNodes = el.childNodes;\n\n    expect(childNodes.length).toBe(3);\n    expect(childNodes[0].childNodes[0].data).toBe('Hello');\n    expect(childNodes[1].childNodes[0].data).toBe('World');\n    expect(childNodes[2].tagName).toBe('DIV');\n\n    inst = render(<MyComponent condition={true} />, el);\n\n    expect(childNodes.length).toBe(2);\n    expect(childNodes[0].childNodes[0].data).toBe('World');\n    expect(childNodes[1].childNodes[0].data).toBe('Hello');\n  });\n\n  it('should render correct when updated', function() {\n    let el = createNodeElement('div');\n\n    class MyComponent extends Component {\n      state = {\n        list: []\n      };\n\n      componentWillMount() {\n        this.setState({\n          list: [1, 2, 3]\n        });\n      }\n\n      render() {\n        return this.state.list.map((item, idx) => {\n          return <span key={idx}>{item}</span>;\n        });\n      }\n    }\n\n    let inst = render(<MyComponent />, el);\n    let childNodes = el.childNodes;\n\n    expect(childNodes.length).toBe(3);\n    expect(childNodes[0].childNodes[0].data).toBe('1');\n    expect(childNodes[1].childNodes[0].data).toBe('2');\n    expect(childNodes[2].childNodes[0].data).toBe('3');\n\n    inst.setState({\n      list: [1, 2, 3, 7, 8, 9]\n    });\n\n    jest.runAllTimers();\n\n    expect(childNodes.length).toBe(6);\n    expect(childNodes[0].childNodes[0].data).toBe('1');\n    expect(childNodes[1].childNodes[0].data).toBe('2');\n    expect(childNodes[2].childNodes[0].data).toBe('3');\n    expect(childNodes[3].childNodes[0].data).toBe('7');\n    expect(childNodes[4].childNodes[0].data).toBe('8');\n    expect(childNodes[5].childNodes[0].data).toBe('9');\n\n    inst.setState({\n      list: [4, 5, 6]\n    });\n    jest.runAllTimers();\n\n    expect(childNodes.length).toBe(3);\n    expect(childNodes[0].childNodes[0].data).toBe('4');\n    expect(childNodes[1].childNodes[0].data).toBe('5');\n    expect(childNodes[2].childNodes[0].data).toBe('6');\n  });\n\n  it('should render correct when updated for null to fragment', function() {\n    let el = createNodeElement('div');\n\n    class Frag extends Component {\n      render() {\n        return [1, 2, 3];\n      }\n    }\n\n    class App extends Component {\n      state = { count: 0 };\n      render() {\n        return (\n          <div>\n            {\n              this.state.count % 2 === 0 ? null :\n                <Frag key=\"a\" />\n            }\n          </div>\n        );\n      }\n    }\n    let instance = render(<App />, el);\n    expect(el.childNodes[0].childNodes).toEqual([]);\n\n    instance.setState({\n      count: 1\n    });\n    jest.runAllTimers();\n\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[0].childNodes[1].data).toBe('2');\n    expect(el.childNodes[0].childNodes[2].data).toBe('3');\n  });\n\n  it('should render correct when updated with first old child existing', function() {\n    let el = createNodeElement('div');\n\n    class Frag extends Component {\n      render() {\n        return [1, 2, 3];\n      }\n    }\n\n    class App extends Component {\n      state = { count: 0 };\n      render() {\n        return (\n          <div>\n            {\n              this.state.count % 2 === 0 ? <div>1</div> :\n                <Frag key=\"a\" />\n            }\n          </div>\n        );\n      }\n    }\n    let instance = render(<App />, el);\n    expect(el.childNodes[0].childNodes[0].childNodes[0].data).toBe('1');\n    instance.setState({\n      count: 1\n    });\n\n    jest.runAllTimers();\n\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[0].childNodes[1].data).toBe('2');\n    expect(el.childNodes[0].childNodes[2].data).toBe('3');\n  });\n\n  it('Fragment and its child Fragment should have the same parent node', function() {\n    let el = createNodeElement('div');\n\n    class Frag extends Component {\n      render() {\n        return [1, 2, [4, 5, [7, 8]], 6];\n      }\n    }\n\n    const instance = render(<Frag />, el);\n    const frgmentInstance = instance._internal._renderedComponent;\n    expect(frgmentInstance._parent).toBe(el);\n    expect(frgmentInstance.__renderedChildren['.2']._parent).toBe(el);\n    expect(frgmentInstance.__renderedChildren['.2'].__renderedChildren['.2']._parent).toBe(el);\n  });\n\n  it('should unmount correct after updated', function() {\n    let el = createNodeElement('div');\n\n    class Frag extends Component {\n      render() {\n        return [1, 2, [3, 4, 5, 6], 7];\n      }\n    }\n\n    class App extends Component {\n      state = { count: 0 };\n      render() {\n        return (\n          <div>\n            {\n              this.state.count === 2 ? null :\n                <Frag />\n            }\n          </div>\n        );\n      }\n    }\n    let instance = render(<App />, el);\n\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[0].childNodes[1].data).toBe('2');\n    expect(el.childNodes[0].childNodes[2].data).toBe('3');\n\n    instance.setState({\n      count: 1\n    });\n\n    jest.runAllTimers();\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[0].childNodes[1].data).toBe('2');\n    expect(el.childNodes[0].childNodes[2].data).toBe('3');\n\n    instance.setState({\n      count: 2\n    });\n\n    jest.runAllTimers();\n    expect(el.childNodes[0].childNodes).toEqual([]);\n  });\n\n  it('should unmount all children', function() {\n    let el = createNodeElement('div');\n\n    class App extends Component {\n      state = {\n        list: [],\n      };\n\n      componentDidMount() {\n        // eslint-disable-next-line\n        this.setState({\n          list: [1, 2, 3]\n        });\n      }\n\n      render() {\n        const { list } = this.state;\n        return list.map(item => <div key={item}>{item}</div>);\n      }\n    }\n\n    let instance = render(<App />, el);\n    jest.runAllTimers();\n    expect(el.childNodes.length).toBe(3);\n\n    Host.driver.removeChildren = (node) => {\n      node.childNodes = [];\n    };\n    instance.setState({ list: [] });\n    jest.runAllTimers();\n\n    delete Host.driver.removeChildren; // Reset driver\n    expect(el.childNodes.length).toBe(0);\n  });\n\n  it('should not cache native node', function() {\n    let el = createNodeElement('div');\n    let instance = null;\n\n    class Child extends Component {\n      state = {\n        count: 2\n      }\n\n      render() {\n        instance = this;\n        const count = this.state.count;\n        if (count === 2) return <div>{count}</div>;\n        return <span>{count}</span>;\n      }\n    }\n\n    class App extends Component {\n      render() {\n        return (\n          [\n            <div key=\"1\">1</div>,\n            <Child key=\"2\" />\n          ]\n        );\n      }\n    }\n\n    const app = render(<App />, el);\n\n    expect(el.childNodes[0].childNodes[0].data).toBe('1');\n    expect(el.childNodes[1].childNodes[0].data).toBe('2');\n\n    instance.setState({\n      count: 3\n    });\n    jest.runAllTimers();\n    const nodes = app[INTERNAL][RENDERED_COMPONENT].__getNativeNode();\n    expect(el.childNodes[1]).toBe(nodes[1]);\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/key.js",
    "content": "/* @jsx createElement */\n\n'use strict';\n\nimport Component from '../component';\nimport createElement from '../../createElement';\nimport Host from '../host';\nimport render from '../../render';\nimport ServerDriver from 'driver-server';\n\ndescribe('Key', function() {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('should unmount and remount if the key changes', function() {\n    let container = createNodeElement('container');\n\n    let mockMount = jest.fn();\n    let mockUnmount = jest.fn();\n\n    class MyComponent extends Component {\n      componentDidMount = mockMount;\n      componentWillUnmount = mockUnmount;\n      render() {\n        return <span>{this.props.text}</span>;\n      }\n    }\n\n    expect(mockMount.mock.calls.length).toBe(0);\n    expect(mockUnmount.mock.calls.length).toBe(0);\n\n    render(<MyComponent text=\"orange\" key=\"A\" />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('orange');\n    expect(mockMount.mock.calls.length).toBe(1);\n    expect(mockUnmount.mock.calls.length).toBe(0);\n\n    // If we change the key, the component is unmounted and remounted\n    render(<MyComponent text=\"green\" key=\"B\" />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('green');\n    expect(mockMount.mock.calls.length).toBe(2);\n    expect(mockUnmount.mock.calls.length).toBe(1);\n\n    // But if we don't change the key, the component instance is reused\n    render(<MyComponent text=\"blue\" key=\"B\" />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('blue');\n    expect(mockMount.mock.calls.length).toBe(2);\n    expect(mockUnmount.mock.calls.length).toBe(1);\n  });\n\n  it('should render right if the key is existed', function() {\n    let container = createNodeElement('container');\n\n    class Foo extends Component {\n      state = {\n        list: [<span key=\"0\">0</span>, <span key=\"1\">1</span>, <span key=\"2\">2</span>]\n      };\n\n      render() {\n        return <div>\n          {this.state.list}\n          {this.state.list[0]}\n        </div>;\n      }\n    }\n\n    expect(() => {\n      render(<Foo value=\"foo\" />, container);\n      expect(container.childNodes[0].childNodes[0].childNodes[0].data).toBe('0');\n      expect(container.childNodes[0].childNodes[1].childNodes[0].data).toBe('1');\n      expect(container.childNodes[0].childNodes[2].childNodes[0].data).toBe('2');\n      expect(container.childNodes[0].childNodes[3].childNodes[0].data).toBe('0');\n    }).toWarnDev('Warning: Encountered two children with the same key \"0\".', {withoutStack: true});\n\n    expect(() => {\n      render(<Foo value=\"bar\" />, container);\n      expect(container.childNodes[0].childNodes[0].childNodes[0].data).toBe('0');\n      expect(container.childNodes[0].childNodes[1].childNodes[0].data).toBe('1');\n      expect(container.childNodes[0].childNodes[2].childNodes[0].data).toBe('2');\n      expect(container.childNodes[0].childNodes[3].childNodes[0].data).toBe('0');\n    }).toWarnDev('Warning: Encountered two children with the same key \"0\".', {withoutStack: true});\n  });\n\n  it('should render right if unshift new element', function() {\n    let container = createNodeElement('container');\n\n    class Foo extends Component {\n      constructor(props) {\n        super(props);\n        this.state = {\n          list: [<span key=\"0\">0</span>, <span key=\"1\">1</span>, <span key=\"2\">2</span>]\n        };\n      }\n\n      componentWillReceiveProps() {\n        this.state.list.unshift(<span key=\"-1\">-1</span>);\n      }\n\n      render() {\n        return <div>\n          {this.state.list}\n        </div>;\n      }\n    }\n\n    render(<Foo />, container);\n    expect(container.childNodes[0].childNodes[0].childNodes[0].data).toBe('0');\n    expect(container.childNodes[0].childNodes[1].childNodes[0].data).toBe('1');\n    expect(container.childNodes[0].childNodes[2].childNodes[0].data).toBe('2');\n\n    render(<Foo value=\"foo\" />, container);\n    expect(container.childNodes[0].childNodes[0].childNodes[0].data).toBe('-1');\n    expect(container.childNodes[0].childNodes[1].childNodes[0].data).toBe('0');\n    expect(container.childNodes[0].childNodes[2].childNodes[0].data).toBe('1');\n    expect(container.childNodes[0].childNodes[3].childNodes[0].data).toBe('2');\n  });\n\n  it('should move to correct position for same key in different element', () => {\n    let container = createNodeElement('container');\n    class App extends Component {\n      state = {count: 0};\n      render() {\n        return (\n          <div>\n            {\n              this.state.count % 2 === 0 ? [<div key=\"a\">1</div>, <span key=\"b\">2</span>] :\n                [<span key=\"b\">2</span>, <span key=\"a\">3</span>]\n            }\n          </div>\n        );\n      }\n    }\n    let instance = render(<App />, container);\n    expect(container.childNodes[0].childNodes[0].childNodes[0].data).toBe('1');\n    expect(container.childNodes[0].childNodes[1].childNodes[0].data).toBe('2');\n\n    instance.setState({count: 1});\n    jest.runAllTimers();\n\n    expect(container.childNodes[0].childNodes[0].childNodes[0].data).toBe('2');\n    expect(container.childNodes[0].childNodes[1].childNodes[0].data).toBe('3');\n  });\n\n  // fixed issue https://github.com/alibaba/rax/issues/2209\n  it('Should not warn when element is \"\"', () => {\n    let container = createNodeElement('container');\n    class App extends Component {\n      render() {\n        return (\n          <div>\n            {\n              [\n                { id: 0, prefix: '', suffix: '' },\n                { id: 1, prefix: '', suffix: '' }\n              ].map((item) => {\n                return (\n                  <div key={item.id}>\n                    {item.prefix}\n                    {item.suffix}\n                  </div>\n                );\n              })\n            }\n          </div>\n        );\n      }\n    }\n\n    expect(() => {\n      render(<App />, container);\n    }).toWarnDev([], {withoutStack: true});\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/native.js",
    "content": "/* @jsx createElement */\n\n'use strict';\n\nimport Component from '../component';\nimport createElement from '../../createElement';\nimport Host from '../host';\nimport render from '../../render';\nimport ServerDriver from 'driver-server';\n\ndescribe('NativeComponent', function() {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('updates a mounted text component in place', function() {\n    let el = createNodeElement('div');\n    let inst = render(<div><span />{'foo'}{'bar'}</div>, el);\n\n    let foo = el.childNodes[0].childNodes[1];\n    let bar = el.childNodes[0].childNodes[2];\n    expect(foo.data).toBe('foo');\n    expect(bar.data).toBe('bar');\n\n    inst = render(<div><span />{'baz'}{'qux'}</div>, el);\n    // After the update, the text nodes should have stayed in place (as opposed\n    // to getting unmounted and remounted)\n    expect(el.childNodes[0].childNodes[1]).toBe(foo);\n    expect(el.childNodes[0].childNodes[2]).toBe(bar);\n    expect(foo.data).toBe('baz');\n    expect(bar.data).toBe('qux');\n  });\n\n  it('can be toggled in and out of the markup', function() {\n    let el = createNodeElement('div');\n    let inst = render(<div>{'foo'}<div />{'bar'}</div>, el);\n\n    let container = el.childNodes[0];\n    let childDiv = container.childNodes[1];\n    let childNodes = container.childNodes;\n    expect(childNodes.length).toBe(3);\n\n    inst = render(<div>{null}<div />{null}</div>, el);\n    container = el.childNodes[0];\n    childNodes = container.childNodes;\n    expect(childNodes.length).toBe(3);\n    expect(childNodes[1]).toBe(childDiv);\n\n    inst = render(<div>{'foo'}<div />{'bar'}</div>, el);\n    container = el.childNodes[0];\n    childNodes = container.childNodes;\n\n    expect(childNodes.length).toBe(3);\n    expect(childNodes[0].data).toBe('foo');\n    expect(childNodes[1]).toBe(childDiv);\n    expect(childNodes[2].data).toBe('bar');\n  });\n\n  it('should append to right position', function() {\n    let el = createNodeElement('div');\n    class Hello1 extends Component {\n      render() {\n        if (this.props.show) {\n          return 'hello1';\n        }\n        return null;\n      }\n    }\n\n    class Hello2 extends Component {\n      render() {\n        if (this.props.show) {\n          return 'hello2';\n        } else {\n          return 'bye';\n        }\n      }\n    }\n\n    class MyComponent extends Component {\n      state = {\n        show: false\n      }\n      render() {\n        return (\n          <div>\n            {'foo'}\n            <Hello1 show={this.state.show} />\n            <Hello2 show={this.state.show} />\n          </div>\n        );\n      }\n    }\n\n    let inst = render(<MyComponent />, el);\n\n    let container = el.childNodes[0];\n    let childNodes = container.childNodes;\n    expect(childNodes.length).toBe(3);\n    expect(childNodes[0].data).toBe('foo');\n    expect(childNodes[1].data).toBe(' empty ');\n    expect(childNodes[2].data).toBe('bye');\n\n    inst.setState({\n      show: true\n    });\n    jest.runAllTimers();\n\n    childNodes = container.childNodes;\n\n    expect(childNodes.length).toBe(3);\n    expect(childNodes[0].data).toBe('foo');\n    expect(childNodes[1].data).toBe('hello1');\n    expect(childNodes[2].data).toBe('hello2');\n  });\n\n  it('should rendering correct even if child did not update when element is same', function() {\n    let container = createNodeElement('div');\n    const child1 = <div key=\"a\">a</div>;\n    const child2 = <div>b</div>;\n    const child3 = <div key=\"c\">c</div>;\n\n    class App extends Component {\n      state = {count: 0};\n      render() {\n        return (\n          <div>\n            {\n              this.state.count === 0\n                ? [<div>d</div>, child1, <div>e</div>, child2, child3]\n                : [child3, <div>e</div>, child2, child1, <div>d</div>]\n            }\n          </div>\n        );\n      }\n    }\n    expect(() => {\n      const instance = render(<App />, container);\n      expect(container.childNodes[0].childNodes[0].childNodes[0].data).toBe('d');\n      expect(container.childNodes[0].childNodes[1].childNodes[0].data).toBe('a');\n      expect(container.childNodes[0].childNodes[2].childNodes[0].data).toBe('e');\n      expect(container.childNodes[0].childNodes[3].childNodes[0].data).toBe('b');\n      expect(container.childNodes[0].childNodes[4].childNodes[0].data).toBe('c');\n\n      instance.setState({count: 1});\n      jest.runAllTimers();\n\n      expect(container.childNodes[0].childNodes[0].childNodes[0].data).toBe('c');\n      expect(container.childNodes[0].childNodes[1].childNodes[0].data).toBe('e');\n      expect(container.childNodes[0].childNodes[2].childNodes[0].data).toBe('b');\n      expect(container.childNodes[0].childNodes[3].childNodes[0].data).toBe('a');\n      expect(container.childNodes[0].childNodes[4].childNodes[0].data).toBe('d');\n    }).toWarnDev('Each child in a list should have a unique \"key\" prop. Check the render method of <App>', {withoutStack: true});\n  });\n\n  it('updates empty children can remove all directly', function() {\n    let el = createNodeElement('div');\n\n    class Frag extends Component {\n      render() {\n        return [1, 2, [3, 4, 5, 6], 7];\n      }\n    }\n\n    class App extends Component {\n      constructor(props) {\n        super();\n        this.state = {count: 0};\n      }\n      render() {\n        return (\n          <div>\n            { this.state.count === 2 ? null : <Frag /> }\n          </div>\n        );\n      }\n    }\n\n    let instance = render(<App />, el);\n    let container = el.childNodes[0];\n\n    expect(container.childNodes.length).toEqual(7);\n\n    instance.setState({ count: 1 });\n    jest.runAllTimers();\n    expect(container.childNodes.length).toEqual(7);\n\n    // Test for fast path to removeChildren.\n    let callRemoveChildrenTimes = 0;\n    Host.driver.removeChildren = (node) => {\n      node.childNodes.length = 0;\n      callRemoveChildrenTimes++;\n    };\n    instance.setState({ count: 2 });\n    jest.runAllTimers();\n    expect(container.childNodes.length).toEqual(0);\n    expect(callRemoveChildrenTimes).toEqual(1);\n    delete Host.driver.removeChildren; // Reset driver\n\n    // Test downgrade logical works.\n    instance.setState({ count: 1 });\n    jest.runAllTimers();\n    instance.setState({ count: 2 });\n    jest.runAllTimers();\n    expect(container.childNodes.length).toEqual(0);\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/purecomponent.js",
    "content": "/* @jsx createElement */\n\nimport Component, { PureComponent } from '../component';\nimport createElement from '../../createElement';\nimport Host from '../host';\nimport render from '../../render';\nimport ServerDriver from 'driver-server';\n\ndescribe('PureComponent', function() {\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('should render', function() {\n    let renders = 0;\n    class MyComponent extends PureComponent {\n      state = {type: 'foo'};\n\n      render() {\n        renders++;\n        return <div />;\n      }\n    }\n\n    let component = render(<MyComponent />);\n    expect(renders).toBe(1);\n\n    component.setState({type: 'foo'});\n    jest.runAllTimers();\n    expect(renders).toBe(1);\n\n    component.setState({type: 'bar'});\n    jest.runAllTimers();\n    expect(renders).toBe(2);\n\n    component.setState({type: 'bar'});\n    jest.runAllTimers();\n    expect(renders).toBe(2);\n  });\n\n  it('can override shouldComponentUpdate', function() {\n    let renders = 0;\n    class MyComponent extends PureComponent {\n      state = {type: 'foo'};\n\n      render() {\n        renders++;\n        return <div />;\n      }\n      shouldComponentUpdate() {\n        return true;\n      }\n    }\n\n    let component = render(<MyComponent />);\n    component.setState({type: 'foo'});\n    jest.runAllTimers();\n    expect(renders).toBe(2);\n  });\n\n  it('extends Component', function() {\n    class MyComponent extends PureComponent {\n      render() {\n        expect(this instanceof Component).toBe(true);\n        expect(this instanceof PureComponent).toBe(true);\n        return <div />;\n      }\n    }\n\n    let component = render(<MyComponent />);\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/reactive.js",
    "content": "'use strict';\n/* @jsx createElement */\n\nimport Component from '../component';\nimport PropTypes from 'prop-types';\nimport createElement from '../../createElement';\nimport Host from '../host';\nimport ServerDriver from 'driver-server';\nimport render from '../../render';\n\nfunction StatelessComponent(props) {\n  return <div>{props.name}</div>;\n}\n\ndescribe('ReactiveComponent', function() {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n  });\n\n  it('should render functional stateless component', function() {\n    let container = createNodeElement('div');\n    render(<StatelessComponent name=\"A\" />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('A');\n  });\n\n  it('should render class stateless component', function() {\n    let container = createNodeElement('div');\n\n    class MyComponent {\n      render() {\n        return <StatelessComponent {...this.props} />;\n      }\n    }\n\n    render(<MyComponent name=\"A\" />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('A');\n  });\n\n  it('should update stateless component', function() {\n    let container = createNodeElement('div');\n\n    class Parent extends Component {\n      render() {\n        return <StatelessComponent {...this.props} />;\n      }\n    }\n\n    render(<Parent name=\"A\" />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('A');\n\n    render(<Parent name=\"B\" />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('B');\n  });\n\n  it('should pass context thru stateless component', function() {\n    let container = createNodeElement('div');\n\n    class Child extends Component {\n      static contextTypes = {\n        test: 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 Component {\n      static childContextTypes = {\n        test: PropTypes.string.isRequired,\n      };\n\n      getChildContext() {\n        return {test: this.props.test};\n      }\n\n      render() {\n        return <Parent />;\n      }\n    }\n\n    render(<GrandParent test=\"foo\" />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('foo');\n\n    render(<GrandParent test=\"bar\" />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('bar');\n  });\n\n\n  it('should support default props and prop types', function() {\n    let container = createNodeElement('div');\n\n    function Child(props) {\n      return <div>{props.test}</div>;\n    }\n    Child.defaultProps = {test: 'test'};\n    Child.propTypes = {test: PropTypes.string};\n\n    render(<Child test=\"foo\" />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('foo');\n  });\n\n  it('should receive context', function() {\n    let container = createNodeElement('div');\n\n    class Parent extends Component {\n      static childContextTypes = {\n        lang: 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\n    Child.contextTypes = {lang: PropTypes.string};\n\n    render(<Parent />, container);\n    expect(container.childNodes[0].childNodes[0].data).toBe('en');\n  });\n\n  it('should allow simple functions to return null', function() {\n    let container = createNodeElement('div');\n\n    function Child() {\n      return null;\n    };\n\n    render(<Child />, container);\n    expect(container.childNodes[0].nodeType).toBe(8);\n  });\n\n  it('should allow simple functions to return false', function() {\n    let container = createNodeElement('div');\n    function Child() {\n      return false;\n    }\n\n    render(<Child />, container);\n    expect(container.childNodes[0].nodeType).toBe(8);\n  });\n});"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/ref.js",
    "content": "'use strict';\n/* @jsx createElement */\n\nimport Component from '../component';\nimport createElement from '../../createElement';\nimport Host from '../host';\nimport render from '../../render';\nimport ServerDriver from 'driver-server';\nimport createRef from '../../createRef';\n\ndescribe('Ref', function() {\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('Allow refs to hop around children correctly', function() {\n    class RefHopsAround extends Component {\n      state = {count: 0};\n\n      moveRef = () => {\n        this.setState({count: this.state.count + 1});\n      };\n\n      render() {\n        let count = this.state.count;\n        /**\n         * What we have here, is three divs with refs (div1/2/3), but a single\n         * moving cursor ref `hopRef` that \"hops\" around the three. We'll call the\n         * `moveRef()` function several times and make sure that the hop ref\n         * points to the correct divs.\n         */\n        return (\n          <div>\n            <div\n              id=\"first\"\n              ref={count % 3 === 0 ? 'hopRef' : 'divOneRef'}\n            />\n            <div\n              id=\"second\"\n              ref={count % 3 === 1 ? 'hopRef' : 'divTwoRef'}\n            />\n            <div\n              id=\"third\"\n              ref={count % 3 === 2 ? 'hopRef' : 'divThreeRef'}\n            />\n          </div>\n        );\n      }\n    }\n\n    let refHopsAround = render(<RefHopsAround />);\n\n    let firstDiv = Host.driver.getElementById('first');\n    let secondDiv = Host.driver.getElementById('second');\n    let thirdDiv = Host.driver.getElementById('third');\n\n    expect(refHopsAround.refs.hopRef).toEqual(firstDiv);\n    expect(refHopsAround.refs.divTwoRef).toEqual(secondDiv);\n    expect(refHopsAround.refs.divThreeRef).toEqual(thirdDiv);\n\n    refHopsAround.moveRef();\n    jest.runAllTimers();\n\n    expect(refHopsAround.refs.divOneRef).toEqual(firstDiv);\n    expect(refHopsAround.refs.hopRef).toEqual(secondDiv);\n    expect(refHopsAround.refs.divThreeRef).toEqual(thirdDiv);\n\n    refHopsAround.moveRef();\n    jest.runAllTimers();\n\n    expect(refHopsAround.refs.divOneRef).toEqual(firstDiv);\n    expect(refHopsAround.refs.divTwoRef).toEqual(secondDiv);\n    expect(refHopsAround.refs.hopRef).toEqual(thirdDiv);\n\n    /**\n     * Make sure that after the third, we're back to where we started and the\n     * refs are completely restored.\n     */\n    refHopsAround.moveRef();\n    jest.runAllTimers();\n\n    expect(refHopsAround.refs.hopRef).toEqual(firstDiv);\n    expect(refHopsAround.refs.divTwoRef).toEqual(secondDiv);\n    expect(refHopsAround.refs.divThreeRef).toEqual(thirdDiv);\n  });\n\n  it('Allow refs to hop around composite children correctly', function() {\n    class Child extends Component {\n      render() {\n        this.id = this.props.id;\n        return <div {...this.props} />;\n      }\n    }\n\n    class RefHopsAround extends Component {\n      state = {count: 0};\n\n      moveRef = () => {\n        this.setState({count: this.state.count + 1});\n      };\n\n      render() {\n        let count = this.state.count;\n        /**\n         * What we have here, is three divs with refs (div1/2/3), but a single\n         * moving cursor ref `hopRef` that \"hops\" around the three. We'll call the\n         * `moveRef()` function several times and make sure that the hop ref\n         * points to the correct divs.\n         */\n        return (\n          <div>\n            <Child\n              id=\"first\"\n              ref={count % 3 === 0 ? 'hopRef' : 'divOneRef'}\n            />\n            <Child\n              id=\"second\"\n              ref={count % 3 === 1 ? 'hopRef' : 'divTwoRef'}\n            />\n            <Child\n              id=\"third\"\n              ref={count % 3 === 2 ? 'hopRef' : 'divThreeRef'}\n            />\n          </div>\n        );\n      }\n    }\n\n    let refHopsAround = render(<RefHopsAround />);\n\n    let firstDiv = 'first';\n    let secondDiv = 'second';\n    let thirdDiv = 'third';\n\n    expect(refHopsAround.refs.hopRef.id).toEqual(firstDiv);\n    expect(refHopsAround.refs.divTwoRef.id).toEqual(secondDiv);\n    expect(refHopsAround.refs.divThreeRef.id).toEqual(thirdDiv);\n\n    refHopsAround.moveRef();\n    jest.runAllTimers();\n\n    expect(refHopsAround.refs.divOneRef.id).toEqual(firstDiv);\n    expect(refHopsAround.refs.hopRef.id).toEqual(secondDiv);\n    expect(refHopsAround.refs.divThreeRef.id).toEqual(thirdDiv);\n\n    refHopsAround.moveRef();\n    jest.runAllTimers();\n\n    expect(refHopsAround.refs.divOneRef.id).toEqual(firstDiv);\n    expect(refHopsAround.refs.divTwoRef.id).toEqual(secondDiv);\n    expect(refHopsAround.refs.hopRef.id).toEqual(thirdDiv);\n\n    /**\n     * Make sure that after the third, we're back to where we started and the\n     * refs are completely restored.\n     */\n    refHopsAround.moveRef();\n    jest.runAllTimers();\n\n    expect(refHopsAround.refs.hopRef.id).toEqual(firstDiv);\n    expect(refHopsAround.refs.divTwoRef.id).toEqual(secondDiv);\n    expect(refHopsAround.refs.divThreeRef.id).toEqual(thirdDiv);\n  });\n\n  it('Always has a value for this.refs', function() {\n    class MyComponent extends Component {\n      render() {\n        return <div />;\n      }\n    }\n\n    let instance = render(<MyComponent />);\n    expect(instance.refs).toEqual({});\n  });\n\n  it('Allow ref accept createRef object', function() {\n    class MyComponent extends Component {\n      constructor(props) {\n        super(props);\n        this.myRef = createRef();\n      }\n      render() {\n        return <div ref={this.myRef} />;\n      }\n    }\n\n    let instance = render(<MyComponent />);\n    expect(instance.myRef.current.tagName).toEqual('DIV');\n  });\n\n  it('Allow createRef object in function object', function() {\n    let myRef = createRef();\n\n    function MyComponent(props) {\n      return (\n        <div ref={myRef} />\n      );\n    }\n\n    render(<MyComponent />);\n    expect(myRef.current.tagName).toEqual('DIV');\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/shallowEqual.js",
    "content": "'use strict';\n\nimport shallowEqual from '../shallowEqual';\n\ndescribe('shallowEqual', () => {\n  it('returns false if either argument is null', () => {\n    expect(shallowEqual(null, {})).toBe(false);\n    expect(shallowEqual({}, null)).toBe(false);\n  });\n\n  it('returns true if both arguments are null or undefined', () => {\n    expect(shallowEqual(null, null)).toBe(true);\n    expect(shallowEqual(undefined, undefined)).toBe(true);\n  });\n\n  it('returns true if arguments are not objects and are equal', () => {\n    expect(shallowEqual(1, 1)).toBe(true);\n  });\n\n  it('returns true if arguments are shallow equal', () => {\n    expect(\n      shallowEqual(\n        {a: 1, b: 2, c: 3},\n        {a: 1, b: 2, c: 3}\n      )\n    ).toBe(true);\n  });\n\n  it('returns true when comparing NaN', () => {\n    expect(shallowEqual(NaN, NaN)).toBe(true);\n\n    expect(\n      shallowEqual(\n        {a: 1, b: 2, c: 3, d: NaN},\n        {a: 1, b: 2, c: 3, d: NaN}\n      )\n    ).toBe(true);\n  });\n\n  it('returns false if arguments are not objects and not equal', () => {\n    expect(\n      shallowEqual(\n        1,\n        2\n      )\n    ).toBe(false);\n  });\n\n  it('returns false if only one argument is not an object', () => {\n    expect(\n      shallowEqual(\n        1,\n        {}\n      )\n    ).toBe(false);\n  });\n\n  it('returns false if first argument has too many keys', () => {\n    expect(\n      shallowEqual(\n        {a: 1, b: 2, c: 3},\n        {a: 1, b: 2}\n      )\n    ).toBe(false);\n  });\n\n  it('returns false if second argument has too many keys', () => {\n    expect(\n      shallowEqual(\n        {a: 1, b: 2},\n        {a: 1, b: 2, c: 3}\n      )\n    ).toBe(false);\n  });\n\n  it('returns false if arguments are not shallow equal', () => {\n    expect(\n      shallowEqual(\n        {a: 1, b: 2, c: {}},\n        {a: 1, b: 2, c: {}}\n      )\n    ).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/vdom/__tests__/text.js",
    "content": "/* @jsx createElement */\n\n'use strict';\n\nimport createElement from '../../createElement';\nimport Host from '../host';\nimport render from '../../render';\nimport ServerDriver from 'driver-server';\n\ndescribe('TextComponent', function() {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n  });\n\n  it('updates a mounted text component in place', function() {\n    let el = createNodeElement('div');\n    let inst = render(<div><span />{'foo'}{'bar'}</div>, el);\n\n    let foo = el.childNodes[0].childNodes[1];\n    let bar = el.childNodes[0].childNodes[2];\n    expect(foo.data).toBe('foo');\n    expect(bar.data).toBe('bar');\n\n    inst = render(<div><span />{'baz'}{'qux'}</div>, el);\n    // After the update, the text nodes should have stayed in place (as opposed\n    // to getting unmounted and remounted)\n    expect(el.childNodes[0].childNodes[1]).toBe(foo);\n    expect(el.childNodes[0].childNodes[2]).toBe(bar);\n    expect(foo.data).toBe('baz');\n    expect(bar.data).toBe('qux');\n  });\n});\n"
  },
  {
    "path": "packages/rax/src/vdom/base.js",
    "content": "import Host from './host';\nimport { INSTANCE, INTERNAL, NATIVE_NODE } from '../constant';\n\n/**\n * Base Component\n */\nexport default class BaseComponent {\n  constructor(element) {\n    this.__currentElement = element;\n  }\n\n  __initComponent(parent, parentInstance, context) {\n    this._parent = parent;\n    this.__parentInstance = parentInstance;\n    this._context = context;\n    this._mountID = Host.__mountID++;\n  }\n\n  __destoryComponent() {\n    if (process.env.NODE_ENV !== 'production') {\n      Host.reconciler.unmountComponent(this);\n    }\n\n    this.__currentElement\n      = this[NATIVE_NODE]\n      = this._parent\n      = this.__parentInstance\n      = this._context\n      = null;\n\n    if (this[INSTANCE]) {\n      this[INSTANCE] = this[INSTANCE][INTERNAL] = null;\n    }\n  }\n\n  __mountComponent(parent, parentInstance, context, nativeNodeMounter) {\n    this.__initComponent(parent, parentInstance, context);\n    this.__mountNativeNode(nativeNodeMounter);\n\n    if (process.env.NODE_ENV !== 'production') {\n      Host.reconciler.mountComponent(this);\n    }\n\n    const instance = {};\n    instance[INTERNAL] = this;\n\n    return instance;\n  }\n\n  unmountComponent(shouldNotRemoveChild) {\n    if (this[NATIVE_NODE] && !shouldNotRemoveChild) {\n      Host.driver.removeChild(this[NATIVE_NODE], this._parent);\n    }\n\n    this.__destoryComponent();\n  }\n\n  __getName() {\n    let currentElement = this.__currentElement;\n    let type = currentElement && currentElement.type;\n\n    return (\n      type && type.displayName ||\n      type && type.name ||\n      type || // Native component's name is type\n      currentElement\n    );\n  }\n\n  __mountNativeNode(nativeNodeMounter) {\n    let nativeNode = this.__getNativeNode();\n    let parent = this._parent;\n\n    if (nativeNodeMounter) {\n      nativeNodeMounter(nativeNode, parent);\n    } else {\n      Host.driver.appendChild(nativeNode, parent);\n    }\n  }\n\n  __getNativeNode() {\n    return this[NATIVE_NODE] == null\n      ? this[NATIVE_NODE] = this.__createNativeNode()\n      : this[NATIVE_NODE];\n  }\n\n  __getPublicInstance() {\n    return this.__getNativeNode();\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/component.js",
    "content": "/**\n * Base component class.\n */\nexport default class Component {\n  constructor(props, context) {\n    this.props = props;\n    this.context = context;\n    this.refs = {};\n  }\n\n  setState(partialState, callback) {\n    // The updater property is injected when composite component mounting\n    this.updater.setState(this, partialState, callback);\n  }\n\n  forceUpdate(callback) {\n    this.updater.forceUpdate(this, callback);\n  }\n}\n\n/**\n * Pure component.\n */\nexport class PureComponent extends Component {\n  constructor(props, context) {\n    super(props, context);\n    this.__isPureComponent = true;\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/composite.js",
    "content": "import ReactiveComponent from './reactive';\nimport updater from './updater';\nimport Host from './host';\nimport { attachRef, updateRef, detachRef } from './ref';\nimport instantiateComponent from './instantiateComponent';\nimport shouldUpdateComponent from './shouldUpdateComponent';\nimport shallowEqual from './shallowEqual';\nimport BaseComponent from './base';\nimport getPrevSiblingNativeNode from './getPrevSiblingNativeNode';\nimport performInSandbox from './performInSandbox';\nimport toArray from '../toArray';\nimport { scheduleLayout } from './scheduler';\nimport { isFunction, isArray } from '../types';\nimport assign from '../assign';\nimport { INSTANCE, INTERNAL, RENDERED_COMPONENT } from '../constant';\nimport invokeFunctionsWithContext from '../invokeFunctionsWithContext';\nimport validateChildKeys from '../validateChildKeys';\nimport { throwError, throwMinifiedError } from '../error';\n\nlet measureLifeCycle;\nif (process.env.NODE_ENV !== 'production') {\n  measureLifeCycle = function(callback, instanceID, type) {\n    Host.measurer && Host.measurer.beforeLifeCycle(instanceID, type);\n    callback();\n    Host.measurer && Host.measurer.afterLifeCycle(instanceID, type);\n  };\n}\n\nfunction scheduleLayoutInSandbox(fn, instance) {\n  scheduleLayout(() => {\n    performInSandbox(fn, instance);\n  });\n}\n\nfunction scheduleLayoutCallbacksInSandbox(callbacks, instance) {\n  if (callbacks) {\n    scheduleLayoutInSandbox(() => {\n      invokeFunctionsWithContext(callbacks, instance);\n    }, instance);\n  }\n}\n\n/**\n * Composite Component\n */\nclass CompositeComponent extends BaseComponent {\n  __mountComponent(parent, parentInstance, context, nativeNodeMounter) {\n    this.__initComponent(parent, parentInstance, context);\n\n    if (process.env.NODE_ENV !== 'production') {\n      this._updateCount = 0;\n      Host.measurer && Host.measurer.beforeMountComponent(this._mountID, this);\n    }\n\n    let currentElement = this.__currentElement;\n    let Component = currentElement.type;\n    let ref = currentElement.ref;\n    let publicProps = currentElement.props;\n    let componentPrototype = Component.prototype;\n\n    // Context process\n    let publicContext = this.__processContext(context);\n\n    // Initialize the public class\n    let instance;\n    let renderedElement;\n\n    performInSandbox(() => {\n      if (componentPrototype && componentPrototype.render) {\n        // Class Component instance\n        instance = new Component(publicProps, publicContext);\n      } else if (isFunction(Component)) {\n        // Functional reactive component with hooks\n        instance = new ReactiveComponent(Component, ref);\n      } else {\n        if (process.env.NODE_ENV !== 'production') {\n          throwError('Invalid component type, expected a class or function component.', Component);\n        } else {\n          throwMinifiedError(6, Component);\n        }\n      }\n    }, parentInstance);\n\n    if (!instance) {\n      return;\n    }\n\n    // These should be set up in the constructor, but as a convenience for\n    // simpler class abstractions, we set them up after the fact.\n    instance.props = publicProps;\n    instance.context = publicContext;\n    instance.refs = {};\n\n    // Inject the updater into instance\n    instance.updater = updater;\n    instance[INTERNAL] = this;\n    this[INSTANCE] = instance;\n\n    // Init state, must be set to an object or null\n    let initialState = instance.state;\n    if (initialState === undefined) {\n      // TODO clone the state?\n      instance.state = initialState = null;\n    }\n\n    if (instance.componentWillMount) {\n      performInSandbox(() => {\n        if (process.env.NODE_ENV !== 'production') {\n          measureLifeCycle(() => {\n            instance.componentWillMount();\n          }, this._mountID, 'componentWillMount');\n        } else {\n          instance.componentWillMount();\n        }\n      }, instance);\n    }\n\n    Host.owner = this;\n    // Process pending state when call setState in componentWillMount\n    instance.state = this.__processPendingState(publicProps, publicContext);\n    const callbacks = this.__pendingCallbacks;\n    this.__pendingCallbacks = null;\n\n    performInSandbox(() => {\n      if (process.env.NODE_ENV !== 'production') {\n        measureLifeCycle(() => {\n          renderedElement = instance.render();\n        }, this._mountID, 'render');\n      } else {\n        renderedElement = instance.render();\n      }\n    }, instance);\n\n    if (process.env.NODE_ENV !== 'production') {\n      validateChildKeys(renderedElement, this.__currentElement.type);\n    }\n\n    Host.owner = null;\n\n    this[RENDERED_COMPONENT] = instantiateComponent(renderedElement);\n    this[RENDERED_COMPONENT].__mountComponent(\n      this._parent,\n      instance,\n      this.__processChildContext(context),\n      nativeNodeMounter\n    );\n\n    if (!currentElement.type._forwardRef && ref) {\n      attachRef(currentElement._owner, ref, this);\n    }\n\n    if (instance.componentDidMount) {\n      scheduleLayoutInSandbox(() => {\n        if (process.env.NODE_ENV !== 'production') {\n          measureLifeCycle(() => {\n            instance.componentDidMount();\n          }, this._mountID, 'componentDidMount');\n        } else {\n          instance.componentDidMount();\n        }\n      }, instance);\n    }\n\n    // Trigger setState callback\n    scheduleLayoutCallbacksInSandbox(callbacks, instance);\n\n    if (process.env.NODE_ENV !== 'production') {\n      scheduleLayout(() => {\n        Host.reconciler.mountComponent(this);\n        Host.measurer && Host.measurer.afterMountComponent(this._mountID);\n      });\n    }\n\n    return instance;\n  }\n\n  unmountComponent(shouldNotRemoveChild) {\n    let instance = this[INSTANCE];\n\n    // Unmounting a composite component maybe not complete mounted\n    // when throw error in component constructor stage\n    if (instance && instance.componentWillUnmount) {\n      performInSandbox(() => {\n        instance.componentWillUnmount();\n      }, instance);\n    }\n\n    if (this[RENDERED_COMPONENT] != null) {\n      let currentElement = this.__currentElement;\n      let ref = currentElement.ref;\n\n      if (!currentElement.type._forwardRef && ref) {\n        detachRef(currentElement._owner, ref, this);\n      }\n\n      this[RENDERED_COMPONENT].unmountComponent(shouldNotRemoveChild);\n      this[RENDERED_COMPONENT] = null;\n    }\n\n    // Reset pending fields\n    // Even if this component is scheduled for another async update,\n    // it would still be ignored because these fields are reset.\n    this.__pendingStateQueue = null;\n    this.__isPendingForceUpdate = false;\n\n    this.__destoryComponent();\n  }\n\n  /**\n   * Filters the context object to only contain keys specified in\n   * `contextTypes`\n   */\n  __processContext(context) {\n    let maskedContext = {};\n    let Component = this.__currentElement.type;\n    let contextTypes = Component.contextTypes;\n\n    if (contextTypes) {\n      for (let contextName in contextTypes) {\n        maskedContext[contextName] = context[contextName];\n      }\n    }\n\n    return maskedContext;\n  }\n\n  __processChildContext(currentContext) {\n    let instance = this[INSTANCE];\n    // The getChildContext method context should be current instance\n    let childContext = instance.getChildContext && instance.getChildContext();\n    if (childContext) {\n      return assign({}, currentContext, childContext);\n    }\n\n    return currentContext;\n  }\n\n  __processPendingState(props, context) {\n    let instance = this[INSTANCE];\n    let queue = this.__pendingStateQueue;\n    if (!queue) {\n      return instance.state;\n    }\n    // Reset pending queue\n    this.__pendingStateQueue = null;\n    let nextState = assign({}, instance.state);\n    for (let i = 0; i < queue.length; i++) {\n      let partial = queue[i];\n      assign(\n        nextState,\n        isFunction(partial) ?\n          partial.call(instance, nextState, props, context) :\n          partial\n      );\n    }\n\n    return nextState;\n  }\n\n  __updateComponent(\n    prevElement,\n    nextElement,\n    prevUnmaskedContext,\n    nextUnmaskedContext\n  ) {\n    let instance = this[INSTANCE];\n\n    // Maybe update component that has already been unmounted or failed mount.\n    if (!instance) {\n      return;\n    }\n\n    performInSandbox(() => {\n      if (process.env.NODE_ENV !== 'production') {\n        Host.measurer && Host.measurer.beforeUpdateComponent(this._mountID, this);\n      }\n\n      let willReceive;\n      let nextContext;\n      let nextProps;\n\n      // Determine if the context has changed or not\n      if (this._context === nextUnmaskedContext) {\n        nextContext = instance.context;\n      } else {\n        nextContext = this.__processContext(nextUnmaskedContext);\n        willReceive = true;\n      }\n\n      // Distinguish between a props update versus a simple state update\n      // Skip checking prop types again -- we don't read component.props to avoid\n      // warning for DOM component props in this upgrade\n      nextProps = nextElement.props;\n\n      if (prevElement !== nextElement) {\n        willReceive = true;\n      }\n\n      if (willReceive && instance.componentWillReceiveProps) {\n        // Calling this.setState() within componentWillReceiveProps will not trigger an additional render.\n        this.__isPendingState = true;\n        instance.componentWillReceiveProps(nextProps, nextContext);\n        this.__isPendingState = false;\n      }\n\n      // Update refs\n      if (this.__currentElement.type._forwardRef) {\n        instance.__prevForwardRef = prevElement.ref;\n        instance._forwardRef = nextElement.ref;\n      } else {\n        updateRef(prevElement, nextElement, this);\n      }\n\n      // Shoud update default\n      let shouldUpdate = true;\n      let prevProps = instance.props;\n      let prevState = instance.state;\n      // TODO: could delay execution processPendingState\n      let nextState = this.__processPendingState(nextProps, nextContext);\n      const callbacks = this.__pendingCallbacks;\n      this.__pendingCallbacks = null;\n\n      // ShouldComponentUpdate is not called when forceUpdate is used\n      if (!this.__isPendingForceUpdate) {\n        if (instance.shouldComponentUpdate) {\n          shouldUpdate = instance.shouldComponentUpdate(nextProps, nextState, nextContext);\n        } else if (instance.__isPureComponent) {\n          // Pure Component\n          shouldUpdate = !shallowEqual(prevProps, nextProps) ||\n            !shallowEqual(prevState, nextState);\n        }\n      }\n\n      if (shouldUpdate) {\n        this.__isPendingForceUpdate = false;\n        // Will set `this.props`, `this.state` and `this.context`.\n        let prevContext = instance.context;\n\n        // Cannot use this.setState() in componentWillUpdate.\n        // If need to update state in response to a prop change, use componentWillReceiveProps instead.\n        if (instance.componentWillUpdate) {\n          instance.componentWillUpdate(nextProps, nextState, nextContext);\n        }\n\n        // Replace with next\n        this.__currentElement = nextElement;\n        this._context = nextUnmaskedContext;\n        instance.props = nextProps;\n        instance.state = nextState;\n        instance.context = nextContext;\n\n        this.__updateRenderedComponent(nextUnmaskedContext);\n\n        if (instance.componentDidUpdate) {\n          scheduleLayoutInSandbox(() => {\n            instance.componentDidUpdate(prevProps, prevState, prevContext);\n          }, instance);\n        }\n\n        if (process.env.NODE_ENV !== 'production') {\n          // Calc update count.\n          this._updateCount++;\n        }\n      } else {\n        // If it's determined that a component should not update, we still want\n        // to set props and state but we shortcut the rest of the update.\n        this.__currentElement = nextElement;\n        this._context = nextUnmaskedContext;\n        instance.props = nextProps;\n        instance.state = nextState;\n        instance.context = nextContext;\n      }\n\n      scheduleLayoutCallbacksInSandbox(callbacks, instance);\n\n      if (process.env.NODE_ENV !== 'production') {\n        scheduleLayout(() => {\n          Host.measurer && Host.measurer.afterUpdateComponent(this._mountID);\n          Host.reconciler.receiveComponent(this);\n        });\n      }\n    }, instance);\n  }\n\n  /**\n   * Call the component's `render` method and update the DOM accordingly.\n   */\n  __updateRenderedComponent(context) {\n    let prevRenderedComponent = this[RENDERED_COMPONENT];\n    let prevRenderedElement = prevRenderedComponent.__currentElement;\n\n    let instance = this[INSTANCE];\n    let nextRenderedElement;\n\n    Host.owner = this;\n\n    if (process.env.NODE_ENV !== 'production') {\n      measureLifeCycle(() => {\n        nextRenderedElement = instance.render();\n      }, this._mountID, 'render');\n    } else {\n      nextRenderedElement = instance.render();\n    }\n\n    Host.owner = null;\n\n    if (shouldUpdateComponent(prevRenderedElement, nextRenderedElement)) {\n      const prevRenderedUnmaskedContext = prevRenderedComponent._context;\n      const nextRenderedUnmaskedContext = this.__processChildContext(context);\n      // If getChildContext existed and invoked when component updated that will make\n      // prevRenderedUnmaskedContext not equal nextRenderedUnmaskedContext under the tree\n      if (prevRenderedElement !== nextRenderedElement || prevRenderedUnmaskedContext !== nextRenderedUnmaskedContext) {\n        // If element type is illegal catch the error\n        prevRenderedComponent.__updateComponent(\n          prevRenderedElement,\n          nextRenderedElement,\n          prevRenderedUnmaskedContext,\n          nextRenderedUnmaskedContext\n        );\n      }\n\n      if (process.env.NODE_ENV !== 'production') {\n        Host.measurer && Host.measurer.recordOperation({\n          instanceID: this._mountID,\n          type: 'update component',\n          payload: {}\n        });\n      }\n    } else {\n      let lastNativeNode = null;\n      let prevNativeNode = prevRenderedComponent.__getNativeNode();\n      // Only prevNativeNode is empty fragment should find the prevSlibingNativeNode\n      // And current root component is fragment, but not need find the prevSlibingNativeNode when init mounting\n      if (isArray(prevNativeNode) && prevNativeNode.length === 0 && instance.__rootID == null) {\n        lastNativeNode = getPrevSiblingNativeNode(prevRenderedComponent);\n      }\n\n      prevRenderedComponent.unmountComponent(true);\n\n      this[RENDERED_COMPONENT] = instantiateComponent(nextRenderedElement);\n      this[RENDERED_COMPONENT].__mountComponent(\n        this._parent,\n        instance,\n        this.__processChildContext(context),\n        (newNativeNode, parent) => {\n          const driver = Host.driver;\n\n          prevNativeNode = toArray(prevNativeNode);\n          newNativeNode = toArray(newNativeNode);\n\n          // If the new length large then prev\n          for (let i = 0; i < newNativeNode.length; i++) {\n            let nativeNode = newNativeNode[i];\n            if (prevNativeNode[i]) {\n              driver.replaceChild(nativeNode, prevNativeNode[i]);\n            } else if (lastNativeNode) {\n              driver.insertAfter(nativeNode, lastNativeNode);\n            } else {\n              driver.appendChild(nativeNode, parent);\n            }\n            lastNativeNode = nativeNode;\n          }\n\n          // If the new length less then prev\n          for (let i = newNativeNode.length; i < prevNativeNode.length; i++) {\n            driver.removeChild(prevNativeNode[i]);\n          }\n        }\n      );\n    }\n  }\n\n  __getNativeNode() {\n    let renderedComponent = this[RENDERED_COMPONENT];\n    if (renderedComponent) {\n      return renderedComponent.__getNativeNode();\n    }\n  }\n\n  __getPublicInstance() {\n    let instance = this[INSTANCE];\n\n    // The functional components cannot be given refs\n    if (instance.__isReactiveComponent) return null;\n\n    return instance;\n  }\n}\n\nexport default CompositeComponent;\n"
  },
  {
    "path": "packages/rax/src/vdom/element.js",
    "content": "import checkPropTypes from 'prop-types/checkPropTypes';\n\nexport default function Element(type, key, ref, props, owner) {\n  let element = {\n    // Built-in properties that belong on the element\n    type,\n    key,\n    ref,\n    props,\n    // Record the component responsible for creating this element.\n    _owner: owner,\n  };\n\n  if (process.env.NODE_ENV !== 'production') {\n    const propTypes = type.propTypes;\n\n    // Validate its props provided by the propTypes definition\n    if (propTypes) {\n      const displayName = type.displayName || type.name;\n      checkPropTypes(\n        propTypes,\n        props,\n        'prop',\n        displayName,\n      );\n    }\n\n    // We make validation flag non-enumerable, so the test framework could ignore it\n    Object.defineProperty(element, '__validated', {\n      configurable: false,\n      enumerable: false,\n      writable: true,\n      value: false\n    });\n\n    // Props is immutable\n    if (Object.freeze) {\n      Object.freeze(props);\n    }\n  }\n\n  return element;\n};\n"
  },
  {
    "path": "packages/rax/src/vdom/empty.js",
    "content": "import Host from './host';\nimport BaseComponent from './base';\n\n/**\n * Empty Component\n */\nclass EmptyComponent extends BaseComponent {\n  __createNativeNode() {\n    return Host.driver.createEmpty(this);\n  }\n  __updateComponent() {\n    return;\n  }\n}\n\nexport default EmptyComponent;\n"
  },
  {
    "path": "packages/rax/src/vdom/flattenChildren.js",
    "content": "import { isArray } from '../types';\n\nfunction traverseChildren(children, result) {\n  if (isArray(children)) {\n    for (let i = 0, l = children.length; i < l; i++) {\n      traverseChildren(children[i], result);\n    }\n  } else {\n    result.push(children);\n  }\n}\n\nexport default function flattenChildren(children) {\n  if (children == null) {\n    return children;\n  }\n  const result = [];\n  traverseChildren(children, result);\n\n  // If length equal 1, return the only one.\n  return result.length - 1 ? result : result[0];\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/fragment.js",
    "content": "import Host from './host';\nimport NativeComponent from './native';\nimport toArray from '../toArray';\nimport { INSTANCE, INTERNAL, NATIVE_NODE } from '../constant';\n\n/**\n * Fragment Component\n */\nclass FragmentComponent extends NativeComponent {\n  __mountComponent(parent, parentInstance, context, nativeNodeMounter) {\n    this.__initComponent(parent, parentInstance, context);\n\n    let instance = this[INSTANCE] = {};\n    instance[INTERNAL] = this;\n\n    const fragment = [];\n    this.__mountChildrenImpl(this._parent, this.__currentElement, context, (nativeNode) => {\n      nativeNode = toArray(nativeNode);\n      for (let i = 0; i < nativeNode.length; i++) {\n        fragment.push(nativeNode[i]);\n      }\n    });\n    if (nativeNodeMounter) {\n      nativeNodeMounter(fragment, parent);\n    } else {\n      for (let i = 0; i < fragment.length; i++) {\n        Host.driver.appendChild(fragment[i], parent);\n      }\n    }\n    if (process.env.NODE_ENV !== 'production') {\n      this.__currentElement.type = FragmentComponent;\n      Host.reconciler.mountComponent(this);\n    }\n\n    return instance;\n  }\n\n  unmountComponent(shouldNotRemoveChild) {\n    if (!shouldNotRemoveChild) {\n      const nativeNode = this.__getNativeNode();\n      for (let i = 0, l = nativeNode.length; i < l; i++) {\n        Host.driver.removeChild(nativeNode[i]);\n      }\n    }\n\n    // Do not need remove child when their parent is removed\n    this.__unmountChildren(true);\n    this.__destoryComponent();\n  }\n\n  __updateComponent(prevElement, nextElement, prevContext, nextContext) {\n    // Replace current element\n    this.__currentElement = nextElement;\n    this.__updateChildren(this.__currentElement, nextContext);\n\n    if (process.env.NODE_ENV !== 'production') {\n      this.__currentElement.type = FragmentComponent;\n      Host.reconciler.receiveComponent(this);\n    }\n  }\n\n  __getNativeNode() {\n    const renderedChildren = this.__renderedChildren || {};\n    return [].concat.apply([], Object.keys(renderedChildren).map(key => renderedChildren[key].__getNativeNode()));\n  }\n}\n\nif (process.env.NODE_ENV !== 'production') {\n  FragmentComponent.displayName = 'Fragment';\n}\n\nexport default FragmentComponent;\n"
  },
  {
    "path": "packages/rax/src/vdom/getElementKeyName.js",
    "content": "import { isString } from '../types';\nimport { warning } from '../error';\n\nexport default function getElementKeyName(children, element, index) {\n  // `element && element.key` will cause elementKey receive \"\" when element is \"\"\n  const elementKey = element ? element.key : void 0;\n  const defaultName = '.' + index.toString(36); // Inner child name default format fallback\n\n  // Key should must be string type\n  if (isString(elementKey)) {\n    let keyName = '$' + elementKey;\n    // Child keys must be unique.\n    let keyUnique = children[keyName] === undefined;\n\n    if (process.env.NODE_ENV !== 'production') {\n      if (!keyUnique) {\n        // Only the first child will be used when encountered two children with the same key\n        warning(`Encountered two children with the same key \"${elementKey}\".`);\n      }\n    }\n\n    return keyUnique ? keyName : defaultName;\n  } else {\n    return defaultName;\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/getNearestParent.js",
    "content": "import { INTERNAL } from '../constant';\n\nexport default function getNearestParent(instance, matcher) {\n  let parent;\n  while (instance && instance[INTERNAL]) {\n    if (matcher(instance)) {\n      parent = instance;\n      break;\n    }\n    instance = instance[INTERNAL].__parentInstance;\n  }\n  return parent;\n}"
  },
  {
    "path": "packages/rax/src/vdom/getPrevSiblingNativeNode.js",
    "content": "import Host from './host';\nimport { isArray } from '../types';\nimport { INTERNAL } from '../constant';\n\n/**\n * This function is usually been used to find the closet previous sibling native node of FragmentComponent.\n * FragmentComponent does not have a native node in the DOM tree, so when it is replaced, the new node has no corresponding location to insert.\n * So we need to look forward from the current mount position of the FragmentComponent to the nearest component which have the native node.\n * @param component\n * @return nativeNode\n */\nexport default function getPrevSiblingNativeNode(component) {\n  let parent = component;\n  while (parent = component.__parentInstance &&\n    component.__parentInstance[INTERNAL]) {\n    if (parent instanceof Host.__Composite) {\n      component = parent;\n      continue;\n    }\n\n    const keys = Object.keys(parent.__renderedChildren);\n    // Find previous sibling native node from current mount index\n    for (let i = component.__mountIndex - 1; i >= 0; i--) {\n      const nativeNode = parent.__renderedChildren[keys[i]].__getNativeNode();\n      // Fragment component always return array\n      if (isArray(nativeNode)) {\n        if (nativeNode.length > 0) {\n          // Get the last one\n          return nativeNode[nativeNode.length - 1];\n        }\n      } else {\n        // Others maybe native node or empty node\n        return nativeNode;\n      }\n    }\n\n    // Find parent over parent\n    if (parent instanceof Host.__Fragment) {\n      component = parent;\n    } else {\n      return null;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/host.js",
    "content": "/*\n * Stateful things in runtime\n */\nexport default {\n  __mountID: 1,\n  __isUpdating: false,\n  // Inject\n  driver: null,\n  // Roots\n  rootComponents: {},\n  rootInstances: {},\n  // Current owner component\n  owner: null,\n};\n"
  },
  {
    "path": "packages/rax/src/vdom/inject.js",
    "content": "import Host from './host';\nimport NativeComponent from './native';\nimport CompositeComponent from './composite';\nimport TextComponent from './text';\nimport FragmentComponent from './fragment';\nimport EmptyComponent from './empty';\nimport reconciler from '../devtools/reconciler';\n\nexport default function inject() {\n  // Inject component class\n  Host.__Empty = EmptyComponent;\n  Host.__Native = NativeComponent;\n  Host.__Text = TextComponent;\n  Host.__Fragment = FragmentComponent;\n  Host.__Composite = CompositeComponent;\n\n  if (process.env.NODE_ENV !== 'production') {\n    // Inject devtool renderer hook\n    Host.reconciler = reconciler;\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/injectRenderOptions.js",
    "content": "import Host from './host';\nimport { throwError, throwMinifiedError } from '../error';\n\nexport default function injectRenderOptions({ driver, measurer }) {\n  // Inject render driver\n  if (!(Host.driver = driver || Host.driver)) {\n    if (process.env.NODE_ENV !== 'production') {\n      throwError('Rax driver not found.');\n    } else {\n      throwMinifiedError(5);\n    }\n  }\n\n  if (process.env.NODE_ENV !== 'production') {\n    // Inject performance measurer\n    Host.measurer = measurer;\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/instance.js",
    "content": "import Host from './host';\nimport createElement from '../createElement';\nimport instantiateComponent from './instantiateComponent';\nimport Root from './root';\nimport {INTERNAL, RENDERED_COMPONENT} from '../constant';\n\n/**\n * Instance manager\n * @NOTE Key should not be compressed, for that will be added to native node and cause DOM Exception.\n */\nconst KEY = '_r';\n\nexport default {\n  set(node, instance) {\n    if (!node[KEY]) {\n      node[KEY] = instance;\n      // Record root instance to roots map\n      if (instance.__rootID) {\n        Host.rootInstances[instance.__rootID] = instance;\n        Host.rootComponents[instance.__rootID] = instance[INTERNAL];\n      }\n    }\n  },\n  get(node) {\n    return node[KEY];\n  },\n  remove(node) {\n    let instance = this.get(node);\n    if (instance) {\n      node[KEY] = null;\n      if (instance.__rootID) {\n        delete Host.rootComponents[instance.__rootID];\n        delete Host.rootInstances[instance.__rootID];\n      }\n    }\n  },\n  mount(element, container, { parent, hydrate }) {\n    if (process.env.NODE_ENV !== 'production') {\n      Host.measurer && Host.measurer.beforeRender();\n    }\n\n    const driver = Host.driver;\n\n    // Real native root node is body\n    if (container == null) {\n      container = driver.createBody();\n    }\n\n    const renderOptions = {\n      element,\n      container,\n      hydrate\n    };\n\n    // Before render callback\n    driver.beforeRender && driver.beforeRender(renderOptions);\n\n    // Get the context from the conceptual parent component.\n    let parentContext;\n    if (parent) {\n      let parentInternal = parent[INTERNAL];\n      parentContext = parentInternal.__processChildContext(parentInternal._context);\n    }\n\n    // Update root component\n    let prevRootInstance = this.get(container);\n    if (prevRootInstance && prevRootInstance.__rootID) {\n      if (parentContext) {\n        // Using __penddingContext to pass new context\n        prevRootInstance[INTERNAL].__penddingContext = parentContext;\n      }\n      prevRootInstance.__update(element);\n\n      // After render callback\n      driver.afterRender && driver.afterRender(renderOptions);\n\n      return prevRootInstance;\n    }\n\n    // Init root component with empty children\n    let renderedComponent = instantiateComponent(createElement(Root));\n    let defaultContext = parentContext || {};\n    let rootInstance = renderedComponent.__mountComponent(container, parent, defaultContext);\n    this.set(container, rootInstance);\n\n    // Mount new element through update queue avoid when there is in rendering phase\n    rootInstance.__update(element);\n\n    // After render callback\n    driver.afterRender && driver.afterRender(renderOptions);\n\n    if (process.env.NODE_ENV !== 'production') {\n      // Devtool render new root hook\n      Host.reconciler.renderNewRootComponent(rootInstance[INTERNAL][RENDERED_COMPONENT]);\n      Host.measurer && Host.measurer.afterRender();\n    }\n\n    return rootInstance;\n  }\n};\n"
  },
  {
    "path": "packages/rax/src/vdom/instantiateComponent.js",
    "content": "import Host from './host';\nimport {isString, isNumber, isArray, isNull, isPlainObject} from '../types';\nimport { throwMinifiedWarn, throwError } from '../error';\n\nexport default function instantiateComponent(element) {\n  let instance;\n\n  if (isPlainObject(element) && element !== null && element.type) {\n    // Special case string values\n    if (isString(element.type)) {\n      instance = new Host.__Native(element);\n    } else {\n      instance = new Host.__Composite(element);\n    }\n  } else if (isString(element) || isNumber(element)) {\n    instance = new Host.__Text(String(element));\n  } else if (isArray(element)) {\n    instance = new Host.__Fragment(element);\n  } else {\n    if (!(element === undefined || isNull(element) || element === false || element === true)) {\n      if (process.env.NODE_ENV !== 'production') {\n        throwError('Invalid child type, expected types: Element instance, string, boolean, array, null, undefined.', element);\n      } else {\n        throwMinifiedWarn(2, element);\n      }\n    }\n\n    instance = new Host.__Empty(element);\n  }\n\n  return instance;\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/native.js",
    "content": "import Host from './host';\nimport { detachRef, attachRef, updateRef } from './ref';\nimport instantiateComponent from './instantiateComponent';\nimport shouldUpdateComponent from './shouldUpdateComponent';\nimport getElementKeyName from './getElementKeyName';\nimport getPrevSiblingNativeNode from './getPrevSiblingNativeNode';\nimport Instance from './instance';\nimport BaseComponent from './base';\nimport toArray from '../toArray';\nimport { isFunction, isArray, isNull } from '../types';\nimport assign from '../assign';\nimport { INSTANCE, INTERNAL, NATIVE_NODE } from '../constant';\n\nconst STYLE = 'style';\nconst CHILDREN = 'children';\nconst TREE = 'tree';\nconst EVENT_PREFIX_REGEXP = /^on[A-Z]/;\n\n/**\n * Native Component\n */\nexport default class NativeComponent extends BaseComponent {\n  __mountComponent(parent, parentInstance, context, nativeNodeMounter) {\n    this.__initComponent(parent, parentInstance, context);\n\n    const currentElement = this.__currentElement;\n    const props = currentElement.props;\n    const type = currentElement.type;\n    const children = props[CHILDREN];\n    const appendType = props.append || TREE; // Default is tree\n\n    // Clone a copy for style diff\n    this.__prevStyleCopy = assign({}, props[STYLE]);\n\n    let instance = {\n      type,\n      props,\n    };\n    instance[INTERNAL] = this;\n\n    this[INSTANCE] = instance;\n\n    if (appendType === TREE) {\n      // Should after process children when mount by tree mode\n      this.__mountChildren(children, context);\n      this.__mountNativeNode(nativeNodeMounter);\n    } else {\n      // Should before process children when mount by node mode\n      this.__mountNativeNode(nativeNodeMounter);\n      this.__mountChildren(children, context);\n    }\n\n    // Ref acttach\n    if (currentElement && currentElement.ref) {\n      attachRef(currentElement._owner, currentElement.ref, this);\n    }\n\n    if (process.env.NODE_ENV !== 'production') {\n      Host.reconciler.mountComponent(this);\n    }\n\n    return instance;\n  }\n\n  __mountChildren(children, context) {\n    if (children == null) return children;\n\n    const nativeNode = this.__getNativeNode();\n    return this.__mountChildrenImpl(nativeNode, toArray(children), context);\n  }\n\n  __mountChildrenImpl(parent, children, context, nativeNodeMounter) {\n    let renderedChildren = this.__renderedChildren = {};\n\n    const renderedChildrenImage = [];\n    for (let i = 0, l = children.length; i < l; i++) {\n      const element = children[i];\n      const renderedChild = instantiateComponent(element);\n      const name = getElementKeyName(renderedChildren, element, i);\n      renderedChildren[name] = renderedChild;\n      renderedChild.__mountIndex = i;\n      // Mount children\n      const mountImage = renderedChild.__mountComponent(\n        parent,\n        this[INSTANCE],\n        context,\n        nativeNodeMounter\n      );\n      renderedChildrenImage.push(mountImage);\n    }\n\n    return renderedChildrenImage;\n  }\n\n  __unmountChildren(shouldNotRemoveChild) {\n    let renderedChildren = this.__renderedChildren;\n\n    if (renderedChildren) {\n      for (let name in renderedChildren) {\n        let renderedChild = renderedChildren[name];\n        renderedChild.unmountComponent(shouldNotRemoveChild);\n      }\n      this.__renderedChildren = null;\n    }\n  }\n\n  unmountComponent(shouldNotRemoveChild) {\n    if (this[NATIVE_NODE]) {\n      let ref = this.__currentElement.ref;\n      if (ref) {\n        detachRef(this.__currentElement._owner, ref, this);\n      }\n\n      Instance.remove(this[NATIVE_NODE]);\n\n      if (!shouldNotRemoveChild) {\n        Host.driver.removeChild(this[NATIVE_NODE], this._parent);\n      }\n    }\n\n    this.__unmountChildren(true);\n\n    this.__prevStyleCopy = null;\n    this.__destoryComponent();\n  }\n\n  __updateComponent(prevElement, nextElement, prevContext, nextContext) {\n    // Replace current element\n    this.__currentElement = nextElement;\n\n    updateRef(prevElement, nextElement, this);\n\n    let prevProps = prevElement.props;\n    let nextProps = nextElement.props;\n\n    this.__updateProperties(prevProps, nextProps);\n\n    // If the prevElement has no child, mount children directly\n    if (prevProps[CHILDREN] == null ||\n      isArray(prevProps[CHILDREN]) && prevProps[CHILDREN].length === 0) {\n      this.__mountChildren(nextProps[CHILDREN], nextContext);\n    } else {\n      this.__updateChildren(nextProps[CHILDREN], nextContext);\n    }\n\n    if (process.env.NODE_ENV !== 'production') {\n      Host.reconciler.receiveComponent(this);\n    }\n  }\n\n  __updateProperties(prevProps, nextProps) {\n    let propKey;\n    let styleName;\n    let styleUpdates;\n    const driver = Host.driver;\n    const nativeNode = this.__getNativeNode();\n\n    for (propKey in prevProps) {\n      // Continue children and null value prop or nextProps has some propKey that do noting\n      if (\n        propKey === CHILDREN ||\n        prevProps[propKey] == null ||\n        // Use hasOwnProperty here for avoid propKey name is some with method name in object proptotype\n        nextProps.hasOwnProperty(propKey)\n      ) {\n        continue;\n      }\n\n      if (propKey === STYLE) {\n        // Remove all style\n        let lastStyle = this.__prevStyleCopy;\n        for (styleName in lastStyle) {\n          styleUpdates = styleUpdates || {};\n          styleUpdates[styleName] = '';\n        }\n        this.__prevStyleCopy = null;\n      } else if (EVENT_PREFIX_REGEXP.test(propKey)) {\n        // Remove event\n        const eventListener = prevProps[propKey];\n\n        if (isFunction(eventListener)) {\n          driver.removeEventListener(\n            nativeNode,\n            propKey.slice(2).toLowerCase(),\n            eventListener\n          );\n        }\n      } else {\n        // Remove attribute\n        driver.removeAttribute(\n          nativeNode,\n          propKey,\n          prevProps[propKey]\n        );\n      }\n    }\n\n    for (propKey in nextProps) {\n      let nextProp = nextProps[propKey];\n      let prevProp = propKey === STYLE ? this.__prevStyleCopy :\n        prevProps != null ? prevProps[propKey] : undefined;\n\n      // Continue children or prevProp equal nextProp\n      if (\n        propKey === CHILDREN ||\n        prevProp === nextProp ||\n        nextProp == null && prevProp == null\n      ) {\n        continue;\n      }\n\n      // Update style\n      if (propKey === STYLE) {\n        if (nextProp) {\n          // Clone property\n          nextProp = this.__prevStyleCopy = assign({}, nextProp);\n        } else {\n          this.__prevStyleCopy = null;\n        }\n\n        if (prevProp != null) {\n          // Unset styles on `prevProp` but not on `nextProp`.\n          for (styleName in prevProp) {\n            if (!nextProp || !nextProp[styleName] && nextProp[styleName] !== 0) {\n              styleUpdates = styleUpdates || {};\n              styleUpdates[styleName] = '';\n            }\n          }\n          // Update styles that changed since `prevProp`.\n          for (styleName in nextProp) {\n            if (prevProp[styleName] !== nextProp[styleName]) {\n              styleUpdates = styleUpdates || {};\n              styleUpdates[styleName] = nextProp[styleName];\n            }\n          }\n        } else {\n          // Assign next prop when prev style is null\n          styleUpdates = nextProp;\n        }\n      } else if (EVENT_PREFIX_REGEXP.test(propKey)) {\n        // Update event binding\n        let eventName = propKey.slice(2).toLowerCase();\n\n        if (isFunction(prevProp)) {\n          driver.removeEventListener(nativeNode, eventName, prevProp, nextProps);\n        }\n\n        if (isFunction(nextProp)) {\n          driver.addEventListener(nativeNode, eventName, nextProp, nextProps);\n        }\n      } else {\n        // Update other property\n        if (nextProp != null) {\n          driver.setAttribute(\n            nativeNode,\n            propKey,\n            nextProp\n          );\n        } else {\n          driver.removeAttribute(\n            nativeNode,\n            propKey,\n            prevProps[propKey]\n          );\n        }\n\n        if (process.env.NODE_ENV !== 'production') {\n          Host.measurer && Host.measurer.recordOperation({\n            instanceID: this._mountID,\n            type: 'update attribute',\n            payload: {\n              [propKey]: nextProp\n            }\n          });\n        }\n      }\n    }\n\n    if (styleUpdates) {\n      if (process.env.NODE_ENV !== 'production') {\n        Host.measurer && Host.measurer.recordOperation({\n          instanceID: this._mountID,\n          type: 'update style',\n          payload: styleUpdates\n        });\n      }\n\n      driver.setStyle(nativeNode, styleUpdates);\n    }\n  }\n\n  __updateChildren(nextChildrenElements, context) {\n    // prev rendered children\n    let prevChildren = this.__renderedChildren;\n    let driver = Host.driver;\n\n    if (nextChildrenElements == null && prevChildren == null) {\n      return;\n    }\n\n    let nextChildren = {};\n\n    if (nextChildrenElements != null) {\n      nextChildrenElements = toArray(nextChildrenElements);\n\n      // Update next children elements\n      for (let index = 0, length = nextChildrenElements.length; index < length; index++) {\n        let nextElement = nextChildrenElements[index];\n        let name = getElementKeyName(nextChildren, nextElement, index);\n        let prevChild = prevChildren && prevChildren[name];\n        let prevElement = prevChild && prevChild.__currentElement;\n        let prevContext = prevChild && prevChild._context;\n\n        // Try to update between the two of some name that has some element type,\n        // and move child in next children loop if need\n        if (prevChild != null && shouldUpdateComponent(prevElement, nextElement)) {\n          if (prevElement !== nextElement || prevContext !== context) {\n            // Pass the same context when updating children\n            prevChild.__updateComponent(prevElement, nextElement, context,\n              context);\n          }\n\n          nextChildren[name] = prevChild;\n        } else {\n          // Unmount the prevChild when some name with nextChild but different element type,\n          // and move child node in next children loop\n          if (prevChild) {\n            prevChild.__unmount = true;\n          }\n          // The child must be instantiated before it's mounted.\n          nextChildren[name] = instantiateComponent(nextElement);\n        }\n      }\n    }\n\n    let parent = this.__getNativeNode();\n    let isFragmentParent = isArray(parent);\n    let prevFirstChild = null;\n    let prevFirstNativeNode = null;\n    let isPrevFirstEmptyFragment = false;\n    let shouldUnmountPrevFirstChild = false;\n    let lastPlacedNode = null;\n\n    // Directly remove all children from component, if nextChildren is empty (null, [], '').\n    // `driver.removeChildren` is optional driver protocol.\n    let shouldRemoveAllChildren = Boolean(\n      driver.removeChildren\n      // nextChildElements == null or nextChildElements is empty\n      && (isNull(nextChildrenElements) || nextChildrenElements && !nextChildrenElements.length)\n      // Fragment parent can not remove parentNode's all child nodes directly.\n      && !isFragmentParent\n    );\n\n    // Unmount children that are no longer present.\n    if (prevChildren != null) {\n      for (let name in prevChildren) {\n        let prevChild = prevChildren[name];\n        let shouldUnmount = prevChild.__unmount || !nextChildren[name];\n\n        // Store old first child ref for append node ahead and maybe delay remove it\n        if (!prevFirstChild) {\n          shouldUnmountPrevFirstChild = shouldUnmount;\n          prevFirstChild = prevChild;\n          prevFirstNativeNode = prevFirstChild.__getNativeNode();\n\n          if (isArray(prevFirstNativeNode)) {\n            isPrevFirstEmptyFragment = prevFirstNativeNode.length === 0;\n            prevFirstNativeNode = prevFirstNativeNode[0];\n          }\n        } else if (shouldUnmount) {\n          prevChild.unmountComponent(shouldRemoveAllChildren);\n        }\n      }\n\n      // 1. When fragment embed fragment updated but prev fragment is empty\n      // that need to get the prev sibling native node.\n      // like: [ [] ] -> [ [1, 2] ]\n      // 2. When prev fragment is empty and update to other type\n      // like: [ [], 1 ] -> [ 1, 2 ]\n      if (isFragmentParent && parent.length === 0 || isPrevFirstEmptyFragment) {\n        lastPlacedNode = getPrevSiblingNativeNode(this);\n      }\n    }\n\n\n    if (nextChildren != null) {\n      // `nextIndex` will increment for each child in `nextChildren`\n      let nextIndex = 0;\n\n      function insertNodes(nativeNodes, parentNode) {\n        // The nativeNodes maybe fragment, so convert to array type\n        nativeNodes = toArray(nativeNodes);\n\n        for (let i = 0, l = nativeNodes.length; i < l; i++) {\n          if (lastPlacedNode) {\n            // Should reverse order when insert new child after lastPlacedNode:\n            // [lastPlacedNode, *newChild1, *newChild2],\n            // And if prev is empty fragment, lastPlacedNode is the prevSiblingNativeNode found.\n            driver.insertAfter(nativeNodes[l - 1 - i], lastPlacedNode);\n          } else if (prevFirstNativeNode) {\n            // [*newChild1, *newChild2, prevFirstNativeNode]\n            driver.insertBefore(nativeNodes[i], prevFirstNativeNode);\n          } else if (parentNode) {\n            // [*newChild1, *newChild2]\n            driver.appendChild(nativeNodes[i], parentNode);\n          }\n        }\n      }\n\n      for (let name in nextChildren) {\n        let nextChild = nextChildren[name];\n        let prevChild = prevChildren && prevChildren[name];\n\n        // Try to move the some key prevChild but current not at the some position\n        if (prevChild === nextChild) {\n          let prevChildNativeNode = prevChild.__getNativeNode();\n\n          if (prevChild.__mountIndex !== nextIndex) {\n            insertNodes(prevChildNativeNode);\n          }\n        } else {\n          // Mount nextChild that in prevChildren there has no some name\n\n          // Fragment extended native component, so if parent is fragment should get this._parent\n          if (isFragmentParent) {\n            parent = this._parent;\n          }\n\n          nextChild.__mountComponent(\n            parent,\n            this[INSTANCE],\n            context,\n            insertNodes // Insert nodes mounter\n          );\n        }\n\n        // Update to the latest mount order\n        nextChild.__mountIndex = nextIndex++;\n\n        // Get the last child\n        lastPlacedNode = nextChild.__getNativeNode();\n\n        if (isArray(lastPlacedNode)) {\n          lastPlacedNode = lastPlacedNode[lastPlacedNode.length - 1];\n        }\n      }\n    }\n\n    if (shouldUnmountPrevFirstChild) {\n      prevFirstChild.unmountComponent(shouldRemoveAllChildren);\n    }\n\n    if (shouldRemoveAllChildren) {\n      driver.removeChildren(this[NATIVE_NODE]);\n    }\n\n    this.__renderedChildren = nextChildren;\n  }\n\n  __createNativeNode() {\n    const instance = this[INSTANCE];\n    const nativeNode = Host.driver.createElement(instance.type, instance.props, this);\n    Instance.set(nativeNode, instance);\n    return nativeNode;\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/performInSandbox.js",
    "content": "import getNearestParent from './getNearestParent';\nimport { scheduler, scheduleLayout } from './scheduler';\nimport { INTERNAL } from '../constant';\n\nexport default function performInSandbox(fn, instance, callback) {\n  try {\n    return fn();\n  } catch (e) {\n    if (callback) {\n      callback(e);\n    } else {\n      handleError(instance, e);\n    }\n  }\n}\n\n/**\n * A class component becomes an error boundary if\n * it defines either (or both) of the lifecycle methods static getDerivedStateFromError() or componentDidCatch().\n * Use static getDerivedStateFromError() to render a fallback UI after an error has been thrown.\n * Use componentDidCatch() to log error information.\n * @param {*} instance\n * @param {*} error\n */\nexport function handleError(instance, error) {\n  let boundary = getNearestParent(instance, parent => {\n    return parent.componentDidCatch || parent.constructor && parent.constructor.getDerivedStateFromError;\n  });\n\n  if (boundary) {\n    scheduleLayout(() => {\n      const boundaryInternal = boundary[INTERNAL];\n      // Should not attempt to recover an unmounting error boundary\n      if (boundaryInternal) {\n        performInSandbox(() => {\n          if (boundary.componentDidCatch) {\n            boundary.componentDidCatch(error);\n          }\n\n          // Update state to the next render to show the fallback UI.\n          if (boundary.constructor && boundary.constructor.getDerivedStateFromError) {\n            const state = boundary.constructor.getDerivedStateFromError(error);\n            boundary.setState(state);\n          }\n        }, boundaryInternal.__parentInstance);\n      }\n    });\n  } else {\n    // Do not break when error happens\n    scheduler(() => {\n      throw error;\n    }, 0);\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/reactive.js",
    "content": "import Host from './host';\nimport Component from './component';\nimport invokeFunctionsWithContext from '../invokeFunctionsWithContext';\nimport { throwMinifiedError } from '../error';\nimport { INTERNAL } from '../constant';\nimport { EMPTY_OBJECT } from '../types';\n\nconst RE_RENDER_LIMIT = 24;\n/**\n * Functional Reactive Component Class Wrapper\n */\nexport default class ReactiveComponent extends Component {\n  constructor(pureRender, ref) {\n    super();\n    // Marked ReactiveComponent.\n    this.__isReactiveComponent = true;\n    // A pure function\n    this.__render = pureRender;\n    this.__hookID = 0;\n    // Number of rerenders\n    this.__reRenders = 0;\n    this.__hooks = {};\n    // Is render scheduled\n    this.__isScheduled = false;\n    this.__shouldUpdate = false;\n    this.__children = null;\n    this.__contexts = {};\n    // Handles store\n    this.didMount = [];\n    this.didUpdate = [];\n    this.willUnmount = [];\n\n    this.state = EMPTY_OBJECT;\n\n    if (pureRender._forwardRef) {\n      this.__prevForwardRef = this._forwardRef = ref;\n    }\n\n    const compares = pureRender.__compares;\n    if (compares) {\n      this.shouldComponentUpdate = (nextProps) => {\n        // Process composed compare\n        let arePropsEqual = true;\n\n        // Compare push in and pop out\n        for (let i = compares.length - 1; i > -1; i--) {\n          if (arePropsEqual = compares[i](this.props, nextProps)) {\n            break;\n          }\n        }\n\n        return !arePropsEqual || this.__prevForwardRef !== this._forwardRef;\n      };\n    }\n  }\n\n  getHooks() {\n    return this.__hooks;\n  }\n\n  getHookID() {\n    return ++this.__hookID;\n  }\n\n  useContext(context) {\n    const contextID = context._contextID;\n    let contextItem = this.__contexts[contextID];\n    if (!contextItem) {\n      const provider = context.__getNearestParentProvider(this);\n      contextItem = this.__contexts[contextID] = {\n        __provider: provider\n      };\n\n      if (provider) {\n        const handleContextChange = (value) => {\n          // Check the last value that maybe alread rerender\n          // avoid rerender twice when provider value changed\n          if (contextItem.__lastValue !== value) {\n            this.__shouldUpdate = true;\n            this.__update();\n          }\n        };\n        provider.__on(handleContextChange);\n        this.willUnmount.push(() => provider.__off(handleContextChange));\n      }\n    }\n\n    return contextItem.__lastValue = contextItem.__provider ?\n      contextItem.__provider.getValue() : context._defaultValue;\n  }\n\n  componentWillMount() {\n    this.__shouldUpdate = true;\n  }\n\n  componentDidMount() {\n    invokeFunctionsWithContext(this.didMount);\n  }\n\n  componentWillReceiveProps() {\n    this.__shouldUpdate = true;\n  }\n\n  componentDidUpdate() {\n    invokeFunctionsWithContext(this.didUpdate);\n  }\n\n  componentWillUnmount() {\n    invokeFunctionsWithContext(this.willUnmount);\n  }\n\n  __update() {\n    this.setState(EMPTY_OBJECT);\n  }\n\n  render() {\n    if (process.env.NODE_ENV !== 'production') {\n      Host.measurer && Host.measurer.beforeRender();\n    }\n\n    this.__hookID = 0;\n    this.__reRenders = 0;\n    this.__isScheduled = false;\n    let children = this.__render(this.props, this._forwardRef ? this._forwardRef : this.context);\n\n    while (this.__isScheduled) {\n      this.__reRenders++;\n      if (this.__reRenders > RE_RENDER_LIMIT) {\n        if (process.env.NODE_ENV !== 'production') {\n          throw new Error('Too many re-renders, the number of renders is limited to prevent an infinite loop.');\n        } else {\n          throwMinifiedError(4);\n        }\n      }\n\n      this.__hookID = 0;\n      this.__isScheduled = false;\n      children = this.__render(this.props, this._forwardRef ? this._forwardRef : this.context);\n    }\n\n    if (this.__shouldUpdate) {\n      this.__children = children;\n      this.__shouldUpdate = false;\n    }\n\n    return this.__children;\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/ref.js",
    "content": "/*\n * Ref manager\n */\nimport { isFunction, isObject } from '../types';\nimport { INSTANCE } from '../constant';\nimport { warning, throwMinifiedWarn } from '../error';\n\nexport function updateRef(prevElement, nextElement, component) {\n  let prevRef = prevElement ? prevElement.ref : null;\n  let nextRef = nextElement ? nextElement.ref : null;\n\n  // Update refs in owner component\n  if (prevRef !== nextRef) {\n    // Detach prev RenderedElement's ref\n    prevRef && detachRef(prevElement._owner, prevRef, component);\n    // Attach next RenderedElement's ref\n    nextRef && attachRef(nextElement._owner, nextRef, component);\n  }\n}\n\nexport function attachRef(ownerComponent, ref, component) {\n  if (!ownerComponent) {\n    if (process.env.NODE_ENV !== 'production') {\n      warning('Ref can not attach because multiple copies of Rax are used.');\n    } else {\n      throwMinifiedWarn(3);\n    }\n    return;\n  }\n\n  let instance = component.__getPublicInstance();\n\n  if (process.env.NODE_ENV !== 'production') {\n    if (instance == null) {\n      warning('Do not attach ref to function component because they don’t have instances.');\n    }\n  }\n\n  if (isFunction(ref)) {\n    ref(instance);\n  } else if (isObject(ref)) {\n    ref.current = instance;\n  } else {\n    ownerComponent[INSTANCE].refs[ref] = instance;\n  }\n}\n\nexport function detachRef(ownerComponent, ref, component) {\n  if (isFunction(ref)) {\n    // When the referenced component is unmounted and whenever the ref changes, the old ref will be called with null as an argument.\n    ref(null);\n  } else {\n    // Must match component and ref could detach the ref on owner when A's before ref is B's current ref\n    let instance = component.__getPublicInstance();\n\n    if (isObject(ref) && ref.current === instance) {\n      ref.current = null;\n    } else if (ownerComponent[INSTANCE].refs[ref] === instance) {\n      delete ownerComponent[INSTANCE].refs[ref];\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/root.js",
    "content": "import Component from './component';\nimport {INTERNAL, RENDERED_COMPONENT} from '../constant';\n\nlet rootID = 1;\n\nclass Root extends Component {\n  constructor() {\n    super();\n    // Using fragment instead of null for avoid create a comment node when init mount\n    this.__element = [];\n    this.__rootID = rootID++;\n  }\n\n  __getPublicInstance() {\n    return this.__getRenderedComponent().__getPublicInstance();\n  }\n\n  __getRenderedComponent() {\n    return this[INTERNAL][RENDERED_COMPONENT];\n  }\n\n  __update(element) {\n    this.__element = element;\n    this.forceUpdate();\n  }\n\n  render() {\n    return this.__element;\n  }\n}\n\nexport default Root;\n"
  },
  {
    "path": "packages/rax/src/vdom/scheduler.js",
    "content": "let updateCallbacks = [];\nlet effectCallbacks = [];\nlet layoutCallbacks = [];\nexport let scheduler = setTimeout;\n\nif (process.env.NODE_ENV !== 'production') {\n  // Wrapper timer for hijack timers in jest\n  scheduler = (callback) => {\n    setTimeout(callback);\n  };\n}\n\nfunction invokeFunctionsWithClear(callbacks) {\n  let callback;\n  while (callback = callbacks.shift()) {\n    callback();\n  }\n}\n\n// Schedule before next render\nexport function schedule(callback) {\n  if (updateCallbacks.length === 0) {\n    scheduler(flush);\n  }\n  updateCallbacks.push(callback);\n}\n\n// Flush before next render\nexport function flush() {\n  invokeFunctionsWithClear(updateCallbacks);\n}\n\nexport function scheduleEffect(callback) {\n  if (effectCallbacks.length === 0) {\n    scheduler(flushEffect);\n  }\n  effectCallbacks.push(callback);\n}\n\nexport function flushEffect() {\n  invokeFunctionsWithClear(effectCallbacks);\n}\n\nexport function scheduleLayout(callback) {\n  layoutCallbacks.push(callback);\n}\n\nexport function flushLayout() {\n  invokeFunctionsWithClear(layoutCallbacks);\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/shallowEqual.js",
    "content": "import { isNull, isObject, EMPTY_OBJECT } from '../types';\n\nconst hasOwnProperty = EMPTY_OBJECT.hasOwnProperty;\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\nexport function is(x, y) {\n  // SameValue algorithm\n  if (x === y) {\n    // Steps 1-5, 7-10\n    // Steps 6.b-6.e: +0 != -0\n    return x !== 0 || 1 / x === 1 / y;\n  } else {\n    // Step 6.a: NaN == NaN\n    return x !== x && y !== y; // eslint-disable-line no-self-compare\n  }\n}\n\n/**\n * Performs equality by iterating through keys on an object and returning false\n * when any key has values which are not strictly equal between the arguments.\n * Returns true when the values of all keys are strictly equal.\n */\nexport default function shallowEqual(objA, objB) {\n  if (is(objA, objB)) {\n    return true;\n  }\n\n  if (!isObject(objA) || isNull(objA) || !isObject(objB) || isNull(objB)) {\n    return false;\n  }\n\n  let keysA = Object.keys(objA);\n  let keysB = Object.keys(objB);\n\n  if (keysA.length !== keysB.length) {\n    return false;\n  }\n\n  // Test for A's keys different from B.\n  for (let i = 0; i < keysA.length; i++) {\n    if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {\n      return false;\n    }\n  }\n\n  return true;\n}\n"
  },
  {
    "path": "packages/rax/src/vdom/shouldUpdateComponent.js",
    "content": "import {isArray, isString, isNumber, isObject, isFalsy} from '../types';\n\nfunction shouldUpdateComponent(prevElement, nextElement) {\n  let prevFalsy = isFalsy(prevElement);\n  let nextFalsy = isFalsy(nextElement);\n  if (prevFalsy || nextFalsy) {\n    return prevFalsy === nextFalsy;\n  }\n\n  if (isArray(prevElement) && isArray(nextElement)) {\n    return true;\n  }\n\n  const isPrevStringOrNumber = isString(prevElement) || isNumber(prevElement);\n  if (isPrevStringOrNumber) {\n    return isString(nextElement) || isNumber(nextElement);\n  } else {\n    // prevElement and nextElement could be array, typeof [] is \"object\"\n    return (\n      isObject(prevElement) &&\n      isObject(nextElement) &&\n      prevElement.type === nextElement.type &&\n      prevElement.key === nextElement.key\n    );\n  }\n}\n\nexport default shouldUpdateComponent;\n"
  },
  {
    "path": "packages/rax/src/vdom/text.js",
    "content": "import Host from './host';\nimport BaseComponent from './base';\n\n/**\n * Text Component\n */\nclass TextComponent extends BaseComponent {\n  __updateComponent(prevElement, nextElement, context) {\n    nextElement = '' + nextElement;\n    // If text is some value that do not update even there number 1 and string \"1\"\n    if (prevElement !== nextElement) {\n      // Replace current element\n      this.__currentElement = nextElement;\n      Host.driver.updateText(this.__getNativeNode(), nextElement);\n\n      if (process.env.NODE_ENV !== 'production') {\n        this._stringText = this.__currentElement;\n        Host.reconciler.receiveComponent(this);\n      }\n    }\n  }\n\n  __createNativeNode() {\n    if (process.env.NODE_ENV !== 'production') {\n      this._stringText = this.__currentElement;\n    }\n    return Host.driver.createText(this.__currentElement, this);\n  }\n}\n\nexport default TextComponent;\n"
  },
  {
    "path": "packages/rax/src/vdom/updater.js",
    "content": "import Host from './host';\nimport { flushEffect, schedule, flushLayout } from './scheduler';\nimport { INTERNAL, RENDERED_COMPONENT } from '../constant';\n\n// Dirty components store\nlet dirtyComponents = [];\n\nfunction getPendingCallbacks(internal) {\n  return internal.__pendingCallbacks;\n}\n\nfunction setPendingCallbacks(internal, callbacks) {\n  return internal.__pendingCallbacks = callbacks;\n}\n\nfunction getPendingStateQueue(internal) {\n  return internal.__pendingStateQueue;\n}\n\nfunction setPendingStateQueue(internal, partialState) {\n  return internal.__pendingStateQueue = partialState;\n}\n\nfunction enqueueCallback(internal, callback) {\n  let callbackQueue = getPendingCallbacks(internal) || setPendingCallbacks(internal, []);\n  callbackQueue.push(callback);\n}\n\nfunction enqueueState(internal, partialState) {\n  let stateQueue = getPendingStateQueue(internal) || setPendingStateQueue(internal, []);\n  stateQueue.push(partialState);\n}\n\nfunction runUpdate(component) {\n  let internal = component[INTERNAL];\n  if (!internal) {\n    return;\n  }\n\n  Host.__isUpdating = true;\n\n  let prevElement = internal.__currentElement;\n  let prevUnmaskedContext = internal._context;\n  let nextUnmaskedContext = internal.__penddingContext || prevUnmaskedContext;\n  internal.__penddingContext = undefined;\n\n  if (getPendingStateQueue(internal) || internal.__isPendingForceUpdate) {\n    internal.__updateComponent(\n      prevElement,\n      prevElement,\n      prevUnmaskedContext,\n      nextUnmaskedContext\n    );\n\n    flushLayout();\n  }\n\n  Host.__isUpdating = false;\n}\n\nfunction mountOrderComparator(c1, c2) {\n  return c2[INTERNAL]._mountID - c1[INTERNAL]._mountID;\n}\n\nfunction performUpdate() {\n  if (Host.__isUpdating) {\n    return schedule(performUpdate);\n  }\n\n  let component;\n  let dirties = dirtyComponents;\n  if (dirties.length > 0) {\n    // Before next render, we will flush all the effects\n    flushEffect();\n    dirtyComponents = [];\n    // Since reconciling a component higher in the owner hierarchy usually (not\n    // always -- see shouldComponentUpdate()) will reconcile children, reconcile\n    // them before their children by sorting the array.\n    if (dirties.length > 1) {\n      dirties = dirties.filter(c => !!c[INTERNAL]).sort(mountOrderComparator);\n    }\n\n    while (component = dirties.pop()) {\n      runUpdate(component);\n    }\n  }\n}\n\nfunction scheduleUpdate(component, shouldAsyncUpdate) {\n  if (dirtyComponents.indexOf(component) < 0) {\n    dirtyComponents.push(component);\n  }\n\n  if (shouldAsyncUpdate) {\n    // If have been scheduled before, do not need schedule again\n    if (dirtyComponents.length > 1) {\n      return;\n    }\n    schedule(performUpdate);\n  } else {\n    performUpdate();\n  }\n}\n\nfunction requestUpdate(component, partialState, callback) {\n  let internal = component[INTERNAL];\n\n  if (!internal) {\n    if (process.env.NODE_ENV !== 'production') {\n      // Block other render\n      Host.__isUpdating = false;\n      console.error(\n        \"Warning: Can't perform a Rax state update on an unmounted component. This \" +\n          'is a no-op, but it indicates a memory leak in your application. To ' +\n          'fix, cancel all subscriptions and asynchronous tasks in %s.',\n        component.__isReactiveComponent\n          ? 'a useEffect cleanup function'\n          : 'the componentWillUnmount method',\n      );\n    }\n    return;\n  }\n\n  if (callback) {\n    enqueueCallback(internal, callback);\n  }\n\n  const hasComponentRendered = internal[RENDERED_COMPONENT];\n\n  // setState\n  if (partialState) {\n    // Function Component should force update\n    if (component.__isReactiveComponent) {\n      internal.__isPendingForceUpdate = true;\n    }\n    enqueueState(internal, partialState);\n    // State pending when request update in componentWillMount and componentWillReceiveProps,\n    // isPendingState default is false value (false or null) and set to true after componentWillReceiveProps,\n    // _renderedComponent is null when componentWillMount exec.\n    if (!internal.__isPendingState && hasComponentRendered) {\n      scheduleUpdate(component, true);\n    }\n  } else {\n    // forceUpdate\n    internal.__isPendingForceUpdate = true;\n\n    if (hasComponentRendered) {\n      scheduleUpdate(component);\n    }\n  }\n}\n\nconst Updater = {\n  setState(component, partialState, callback) {\n    // Flush all effects first before update state\n    if (!Host.__isUpdating) {\n      flushEffect();\n    }\n    requestUpdate(component, partialState, callback);\n  },\n  forceUpdate(component, callback) {\n    requestUpdate(component, null, callback);\n  }\n};\n\nexport default Updater;\n"
  },
  {
    "path": "packages/rax/src/version.js",
    "content": "export default process.env.RAX_VERSION;\n"
  },
  {
    "path": "packages/rax-app/README.md",
    "content": "# Rax App\n\n## Usage\n```js\nimport { runApp } from 'rax-app';\nimport appConfig from './app.json';\n\nrunApp(appConfig);\n```\n\n## API\n* runApp(appConfig)\n* withRouter(Component)\n* useAppLaunch(callback)\n* usePageShow(callback)\n* usePageHide(callback)"
  },
  {
    "path": "packages/rax-app/package.json",
    "content": "{\n  \"name\": \"rax-app\",\n  \"version\": \"2.3.6\",\n  \"description\": \"Rax application framework for univesal app.\",\n  \"main\": \"lib/index.js\",\n  \"module\": \"es/index.js\",\n  \"author\": \"Rax Team\",\n  \"npmTag\": \"release-2\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"dependencies\": {\n    \"create-app-shared\": \"^0.1.12\",\n    \"miniapp-renderer\": \"^0.1.5\",\n    \"rax-app-renderer\": \"^0.1.3\",\n    \"driver-universal\": \"^3.1.0\",\n    \"rax-pwa\": \"^2.0.0\",\n    \"rax-use-router\": \"^3.0.0\",\n    \"universal-env\": \"^3.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.8\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-app/src/App.js",
    "content": "import { createElement, useState, useEffect, Fragment } from 'rax';\nimport { useRouter } from 'rax-use-router';\nimport { isWeb } from 'universal-env';\nimport { Navigation, TabBar } from 'rax-pwa';\n\nconst initialDataFromSSR = global.__INITIAL_DATA__;\n\nfunction _isNullableComponent(component) {\n  return !component || Array.isArray(component) && component.length === 0;\n}\n\nexport default function App(props) {\n  const { appConfig, history, routes, pageProps, InitialComponent } = props;\n  const { component } = useRouter(() => ({ history, routes, InitialComponent }));\n\n  if (_isNullableComponent(component)) {\n    // Return null directly if not matched.\n    return null;\n  } else {\n    const [pageInitialProps, setPageInitialProps] = useState(\n      // If SSR is enabled, set pageInitialProps: {pagePath: pageData}\n      initialDataFromSSR ? { [initialDataFromSSR.pagePath || '']: initialDataFromSSR.pageData || {} } : {}\n    );\n\n    // If SSR is enabled, process getInitialProps method\n    if (isWeb && initialDataFromSSR && component.getInitialProps && !pageInitialProps[component.__path]) {\n      useEffect(() => {\n        const getInitialPropsPromise = component.getInitialProps();\n\n        // Check getInitialProps returns promise.\n        if (process.env.NODE_ENV !== 'production') {\n          if (!getInitialPropsPromise.then) {\n            throw new Error('getInitialProps should be async function or return a promise. See detail at \"' + component.name + '\".');\n          }\n        }\n\n        getInitialPropsPromise.then((nextDefaultProps) => {\n          if (nextDefaultProps) {\n            // Process pageData from SSR\n            const pageData = initialDataFromSSR && initialDataFromSSR.pagePath === component.__path ? initialDataFromSSR.pageData : {};\n            // Do not cache getInitialPropsPromise result\n            setPageInitialProps(Object.assign({}, { [component.__path]: Object.assign({}, pageData, nextDefaultProps) }));\n          }\n        }).catch((error) => {\n          // In case of uncaught promise.\n          throw error;\n        });\n      });\n      // Early return null if initialProps were not get.\n      return null;\n    }\n\n    if (isWeb) {\n      return createElement(\n        Navigation,\n        Object.assign(\n          { appConfig, component, history, location: history.location, routes, InitialComponent },\n          pageInitialProps[component.__path],\n          pageProps\n        )\n      );\n    }\n\n    return createElement(\n      Fragment,\n      {},\n      createElement(component, Object.assign({ history, location: history.location, routes, InitialComponent }, pageInitialProps[component.__path], pageProps)),\n      createElement(TabBar, { history, config: appConfig.tabBar })\n    );\n  }\n}\n"
  },
  {
    "path": "packages/rax-app/src/index.js",
    "content": "import { createElement, render as raxRender, useEffect, Component } from 'rax';\nimport { withRouter as raxWithRouter } from 'rax-use-router';\nimport createShareAPI from 'create-app-shared';\nimport raxAppRenderer from 'rax-app-renderer';\nimport miniappRenderer from 'miniapp-renderer';\nimport DriverUniversal from 'driver-universal';\nimport { isWeChatMiniProgram, isMiniApp, isByteDanceMicroApp, isWeb, isKraken } from 'universal-env';\nimport App from './App';\n\nconst initialDataFromSSR = global.__INITIAL_DATA__;\n\nlet app;\nfunction mount(appInstance, rootEl) {\n  return app = raxRender(appInstance, rootEl, {\n    driver: DriverUniversal\n  });\n}\n\nfunction unmount() {\n  return app._internal.unmountComponent.bind(app._internal);\n}\n\nconst {\n  getHistory,\n  createHistory,\n  withRouter,\n  withPageLifeCycle,\n  usePageHide,\n  usePageShow,\n  collectAppLifeCycle,\n  addAppLifeCycle,\n  emitLifeCycles,\n  registerNativeEventListeners,\n  addNativeEventListener,\n  removeNativeEventListener,\n  pathRedirect\n} = createShareAPI({\n  withRouter: raxWithRouter,\n  createElement,\n  useEffect\n});\n\nfunction useAppShow(callback) {\n  addAppLifeCycle('show', callback);\n}\n\nfunction useAppLaunch(callback) {\n  addAppLifeCycle('launch', callback);\n}\n\nfunction useAppShare(callback) {\n  addAppLifeCycle('share', callback);\n}\n\nfunction useAppError(callback) {\n  addAppLifeCycle('error', callback);\n}\n\nfunction useAppHide(callback) {\n  addAppLifeCycle('hide', callback);\n}\n\nfunction usePageNotFound(callback) {\n  addAppLifeCycle('notfound', callback);\n}\n\nfunction runApp(staticConfig, dynamicConfig = {}) {\n  let renderer = raxAppRenderer;\n  let createAppInstance;\n  let pageProps;\n  const appConfig = {\n    app: {\n      rootId: 'root'\n    },\n    router: {}\n  };\n\n  if (dynamicConfig.dynamicConfig) {\n    Object.assign(appConfig, {\n      app: dynamicConfig\n    });\n  } else {\n    pageProps = dynamicConfig;\n  }\n\n  const { shell, routes } = staticConfig;\n  if (isWeChatMiniProgram || isMiniApp || isByteDanceMicroApp) {\n    renderer = miniappRenderer;\n  } else {\n    createAppInstance = (initialComponent) => {\n      const history = getHistory();\n      let appInstance = createElement(App, {\n        appConfig: staticConfig,\n        history,\n        routes,\n        pageProps,\n        InitialComponent: initialComponent\n      });\n\n      if (shell) {\n        const shellData = initialDataFromSSR ? initialDataFromSSR.shellData : null;\n        appInstance = createElement(shell.component, { data: shellData }, appInstance);\n      }\n\n      return appInstance;\n    };\n  }\n\n\n  renderer({\n    createBaseApp: () => {\n      let type;\n      if (initialDataFromSSR) {\n        type = 'browser';\n      } else if (isWeb && !isKraken) {\n        type = 'hash';\n      }\n      const history = createHistory({ routes, customHistory: staticConfig.history, type });\n      appConfig.router.history = history;\n      appConfig.router.type = type;\n      collectAppLifeCycle(appConfig);\n      return {\n        appConfig,\n      };\n    },\n    setAppConfig: () => {},\n    createHistory,\n    staticConfig,\n    appConfig,\n    pageProps,\n    getHistory,\n    pathRedirect,\n    createAppInstance,\n    emitLifeCycles\n  }, {\n    createElement,\n    Component,\n    mount,\n    unmount\n  });\n}\n\nexport {\n  withRouter,\n  withPageLifeCycle,\n  usePageHide,\n  usePageShow,\n  registerNativeEventListeners,\n  addNativeEventListener,\n  removeNativeEventListener,\n  runApp,\n  useAppLaunch,\n  useAppShare,\n  useAppError,\n  useAppShow,\n  useAppHide,\n  usePageNotFound\n};\n"
  },
  {
    "path": "packages/rax-children/README.md",
    "content": "# rax-children"
  },
  {
    "path": "packages/rax-children/package.json",
    "content": "{\n  \"name\": \"rax-children\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Rax Children\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"rax\": \"^1.0.0\",\n    \"rax-clone-element\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-children/src/__tests__/childern.js",
    "content": "/* @jsx createElement */\n\nimport { createElement, Component } from 'rax';\nimport cloneElement from 'rax-clone-element';\nimport Children from '../';\n\ndescribe('Children', () => {\n  class WrapComponent extends Component {\n    render() {\n      return (\n        <div>\n          {Children.only(this.props.children, this.props.mapFn, this)}\n        </div>\n      );\n    }\n  }\n\n  it('should support identity for simple', () => {\n    var context = {};\n    var callback = jest.fn(function(kid, index) {\n      expect(this).toBe(context);\n      return kid;\n    });\n\n    var simpleKid = <span key=\"simple\" />;\n\n    var instance = <div>{simpleKid}</div>;\n    Children.forEach(instance.props.children, callback, context);\n    expect(callback).toHaveBeenCalledWith(simpleKid, 0);\n\n    var callback2 = jest.fn(function(kid, index) {\n      expect(this).toBe(context);\n      return kid;\n    });\n    Children.map(\n      instance.props.children,\n      callback2,\n      context,\n    );\n    expect(callback2).toHaveBeenCalledWith(simpleKid, 0);\n  });\n\n\n  it('should invoke callback with the right context', () => {\n    var lastContext;\n    var callback = function(kid, index) {\n      lastContext = this;\n      return this;\n    };\n\n    // TODO: Use an object to test, after non-object fragments has fully landed.\n    var scopeTester = 'scope tester';\n\n    var simpleKid = <span key=\"simple\" />;\n    var instance = <div>{simpleKid}</div>;\n    Children.forEach(instance.props.children, callback, scopeTester);\n    expect(lastContext).toBe(scopeTester);\n\n    var mappedChildren = Children.map(\n      instance.props.children,\n      callback,\n      scopeTester,\n    );\n\n    expect(Children.count(mappedChildren)).toBe(1);\n    expect(mappedChildren[0]).toBe(scopeTester);\n  });\n\n  it('should return 0 for null children', () => {\n    var numberOfChildren = Children.count(null);\n    expect(numberOfChildren).toBe(0);\n  });\n\n  it('should return 0 for undefined children', () => {\n    var numberOfChildren = Children.count(undefined);\n    expect(numberOfChildren).toBe(0);\n  });\n\n  it('should return 1 for single child', () => {\n    var simpleKid = <span key=\"simple\" />;\n    var instance = <div>{simpleKid}</div>;\n    var numberOfChildren = Children.count(instance.props.children);\n    expect(numberOfChildren).toBe(1);\n  });\n\n  it('should count the number of children in flat structure', () => {\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\n    var instance = (\n      <div>\n        {zero}\n        {one}\n        {two}\n        {three}\n        {four}\n      </div>\n    );\n    var numberOfChildren = Children.count(instance.props.children);\n    expect(numberOfChildren).toBe(5);\n  });\n\n  it('should count the number of children in nested structure', () => {\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=\"keyFive\" />;\n\n    var instance = (\n      <div>\n        {[[[zero, one, two], [three, four], five], null]}\n      </div>\n    );\n    var numberOfChildren = Children.count(instance.props.children);\n    expect(numberOfChildren).toBe(7);\n  });\n\n  it('should flatten children to an array', () => {\n    expect(Children.toArray(undefined)).toEqual([]);\n    expect(Children.toArray(null)).toEqual([]);\n\n    expect(Children.toArray(<div />).length).toBe(1);\n    expect(Children.toArray([<div />]).length).toBe(1);\n    expect(Children.toArray(<div />)[0].key).toBe(\n      Children.toArray([<div />])[0].key,\n    );\n\n    var flattened = Children.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    // expect(flattened[1].key).not.toBe(flattened[3].key);\n\n    var reversed = Children.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(Children.toArray([1, 'two', null, undefined, true])).toEqual([\n    //  1,\n    //  'two',\n    // ]);\n  });\n\n  it('should fail when passed two children', () => {\n    expect(function() {\n      var instance = (\n        <WrapComponent>\n          <div />\n          <span />\n        </WrapComponent>\n      );\n      Children.only(instance.props.children);\n    }).toThrow();\n  });\n\n  it('should fail when passed nully values', () => {\n    expect(function() {\n      var instance = (\n        <WrapComponent>\n          {null}\n        </WrapComponent>\n      );\n      Children.only(instance.props.children);\n    }).toThrow();\n\n    expect(function() {\n      var instance = (\n        <WrapComponent>\n          {undefined}\n        </WrapComponent>\n      );\n      Children.only(instance.props.children);\n    }).toThrow();\n  });\n\n  it('should fail when passed interpolated two array children', () => {\n    expect(function() {\n      var instance = (\n        <WrapComponent>\n          {[<span key=\"abc\" />, <span key=\"def\" />]}\n        </WrapComponent>\n      );\n      Children.only(instance.props.children);\n    }).toThrow();\n  });\n\n  it('should not fail when passed interpolated single child', () => {\n    expect(function() {\n      var instance = (\n        <WrapComponent>\n          {<span />}\n        </WrapComponent>\n      );\n      Children.only(instance.props.children);\n    }).not.toThrow();\n  });\n\n  it('should return the only child', () => {\n    var instance = (\n      <WrapComponent>\n        <span />\n      </WrapComponent>\n    );\n    expect(Children.only(instance.props.children)).toEqual(<span />);\n  });\n\n  it('should not throw if key provided is a dupe with array key', () => {\n    var zero = <div />;\n    var one = <div key=\"0\" />;\n\n    var mapFn = function() {\n      return null;\n    };\n\n    var instance = (\n      <div>\n        {zero}\n        {one}\n      </div>\n    );\n\n    expect(function() {\n      Children.map(instance.props.children, mapFn);\n    }).not.toThrow();\n  });\n\n  it('should use the same key for a cloned element', () => {\n    var instance = (\n      <div>\n        <div />\n      </div>\n    );\n\n    var mapped = Children.map(\n      instance.props.children,\n      element => element,\n    );\n\n    var mappedWithClone = Children.map(instance.props.children, element =>\n      cloneElement(element),\n    );\n\n    expect(mapped[0].key).toBe(mappedWithClone[0].key);\n  });\n\n  it('should use the same key for a cloned element with key', () => {\n    var instance = (\n      <div>\n        <div key=\"unique\" />\n      </div>\n    );\n\n    var mapped = Children.map(\n      instance.props.children,\n      element => element,\n    );\n\n    var mappedWithClone = Children.map(instance.props.children, element =>\n      cloneElement(element, {key: 'unique'}),\n    );\n\n    expect(mapped[0].key).toBe(mappedWithClone[0].key);\n  });\n});\n"
  },
  {
    "path": "packages/rax-children/src/index.js",
    "content": "import { shared } from 'rax';\n\nconst { flattenChildren } = shared;\n\nfunction convertChildrenToArray(children) {\n  // flatten children\n  children = flattenChildren(children, []);\n  return Array.isArray(children) ? children : [].concat(children);\n}\n\nconst Children = {\n  map(children, fn, ctx) {\n    if (children == null) return null;\n    children = convertChildrenToArray(children);\n    return children.map((child, index) => fn.call(ctx, child, index));\n  },\n  forEach(children, fn, ctx) {\n    if (children == null) return null;\n    children = convertChildrenToArray(children);\n    children.forEach((child, index) => fn.call(ctx, child, index));\n  },\n  count(children) {\n    if (children == null) return 0;\n    return convertChildrenToArray(children).length;\n  },\n  only(children) {\n    // `only` receive rax element child\n    // null value is not acceptable\n    children = Children.toArray(children);\n    if (children.length !== 1) throw new Error('Children.only: expected to receive a single element child.');\n    return children[0];\n  },\n  toArray(children) {\n    if (children == null) return [];\n    // `toArray` filter null value\n    return convertChildrenToArray(children).filter(child => child !== null);\n  }\n};\n\nexport default Children;\n"
  },
  {
    "path": "packages/rax-clone-element/README.md",
    "content": "# rax-clone-element"
  },
  {
    "path": "packages/rax-clone-element/package.json",
    "content": "{\n  \"name\": \"rax-clone-element\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Rax cloneElement\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"dependencies\": {\n    \"rax-is-valid-element\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"rax\": \"^1.0.0\",\n    \"driver-server\": \"^1.0.0\",\n    \"rax-create-factory\": \"^1.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-clone-element/src/__tests__/cloneElement.js",
    "content": "\n/* @jsx createElement */\n\nimport cloneElement from '../';\nimport { createElement, Component, render, shared } from 'rax';\nimport createFactory from 'rax-create-factory';\nimport ServerDriver from 'driver-server';\n\nconst { Host } = shared;\n\ndescribe('cloneElement', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n  });\n\n  class ComponentClass extends Component {\n    render() {\n      return <div />;\n    }\n  }\n\n  it('should use the same key for a cloned element', function() {\n    var instance =\n      <div>\n        <div />\n      </div>\n    ;\n\n    var element = instance.props.children;\n    var cloned = cloneElement(element);\n\n    expect(cloned.key).toBe(element.key);\n  });\n\n  it('should clone a DOM component with new props', function() {\n    const container = createNodeElement('div');\n    class Grandparent {\n      render() {\n        return <Parent child={<div className=\"child\" />} />;\n      }\n    }\n\n    class Parent {\n      render() {\n        return (\n          <div className=\"parent\">\n            {cloneElement(this.props.child, { className: 'xyz' })}\n          </div>\n        );\n      }\n    }\n\n    render(<Grandparent />, container);\n    expect(container.childNodes[0].childNodes[0].attributes.class).toBe('xyz');\n  });\n\n  it('should clone a composite component with new props', function() {\n    const container = createNodeElement('div');\n\n    class Child {\n      render() {\n        return <div className={this.props.className} />;\n      }\n    }\n\n    class Grandparent {\n      render() {\n        return <Parent child={<Child className=\"child\" />} />;\n      }\n    }\n\n    class Parent {\n      render() {\n        return (\n          <div className=\"parent\">\n            {cloneElement(this.props.child, { className: 'xyz' })}\n          </div>\n        );\n      }\n    }\n\n    render(<Grandparent />, container);\n    expect(container.childNodes[0].childNodes[0].attributes.class).toBe('xyz');\n  });\n\n  it('should keep the original ref if it is not overridden', function() {\n    class Grandparent {\n      render() {\n        return <Parent child={<div ref=\"yolo\" />} />;\n      }\n    }\n\n    class Parent {\n      render() {\n        return (\n          <div>\n            {cloneElement(this.props.child, { className: 'xyz' })}\n          </div>\n        );\n      }\n    }\n\n    var component = render(<Grandparent />);\n    expect(component.refs.yolo.tagName).toBe('DIV');\n  });\n\n  it('should transfer the key property', function() {\n    class MyComponent {\n      render() {\n        return null;\n      }\n    }\n    var clone = cloneElement(<MyComponent />, {key: 'xyz'});\n    expect(clone.key).toBe('xyz');\n  });\n\n  it('should transfer children', function() {\n    class MyComponent {\n      render() {\n        expect(this.props.children).toBe('xyz');\n        return <div />;\n      }\n    }\n\n    render(\n      cloneElement(<MyComponent />, {children: 'xyz'})\n    );\n  });\n\n  it('should shallow clone children', function() {\n    class MyComponent {\n      render() {\n        expect(this.props.children).toBe('xyz');\n        return <div />;\n      }\n    }\n\n    render(\n      cloneElement(<MyComponent>xyz</MyComponent>, {})\n    );\n  });\n\n  it('should accept children as rest arguments', function() {\n    class MyComponent {\n      render() {\n        return null;\n      }\n    }\n\n    var clone = cloneElement(\n      <MyComponent>xyz</MyComponent>,\n      { children: <MyComponent /> },\n      <div />,\n      <span />\n    );\n\n    expect(clone.props.children).toEqual([\n      <div />,\n      <span />,\n    ]);\n  });\n\n  it('should override children if undefined is provided as an argument', function() {\n    var element = createElement(ComponentClass, {\n      children: 'text',\n    }, undefined);\n    expect(element.props.children).toBe(undefined);\n\n    var element2 = cloneElement(createElement(ComponentClass, {\n      children: 'text',\n    }), {}, undefined);\n    expect(element2.props.children).toBe(undefined);\n  });\n\n\n  it('should support keys and refs', function() {\n    class Parent {\n      render() {\n        var clone = cloneElement(this.props.children, {key: 'xyz', ref: 'xyz'});\n        expect(clone.key).toBe('xyz');\n        expect(clone.ref).toBe('xyz');\n        return <div>{clone}</div>;\n      }\n    }\n\n    class Grandparent {\n      render() {\n        return <Parent ref=\"parent\"><span key=\"abc\" /></Parent>;\n      }\n    }\n\n    var component = render(<Grandparent />);\n    expect(component.refs.parent.refs.xyz.tagName).toBe('SPAN');\n  });\n\n  it('should steal the ref if a new ref is specified', function() {\n    class Parent {\n      render() {\n        var clone = cloneElement(this.props.children, {ref: 'xyz'});\n        return <div>{clone}</div>;\n      }\n    }\n\n    class Grandparent {\n      render() {\n        return <Parent ref=\"parent\"><span ref=\"child\" /></Parent>;\n      }\n    }\n\n    var component = render(<Grandparent />);\n    expect(component.refs.child).toBeUndefined();\n    expect(component.refs.parent.refs.xyz.tagName).toBe('SPAN');\n  });\n\n\n  it('should overwrite props', function() {\n    class MyComponent {\n      render() {\n        expect(this.props.myprop).toBe('xyz');\n        return <div />;\n      }\n    }\n\n    render(\n      cloneElement(<MyComponent myprop=\"abc\" />, {myprop: 'xyz'})\n    );\n  });\n\n\n  it('should normalize props with default values', function() {\n    class MyComponent {\n      static defaultProps = {prop: 'testKey'};\n      render() {\n        return <span />;\n      }\n    }\n\n    var instance = createElement(MyComponent);\n    var clonedInstance = cloneElement(instance, {prop: undefined});\n    expect(clonedInstance.props.prop).toBe('testKey');\n    var clonedInstance2 = cloneElement(instance, {prop: null});\n    expect(clonedInstance2.props.prop).toBe(null);\n\n    var instance2 = createElement(MyComponent, {prop: 'newTestKey'});\n    var cloneInstance3 = cloneElement(instance2, {prop: undefined});\n    expect(cloneInstance3.props.prop).toBe('testKey');\n    var cloneInstance4 = cloneElement(instance2, {});\n    expect(cloneInstance4.props.prop).toBe('newTestKey');\n  });\n\n  it('should ignore key and ref warning getters', function() {\n    var elementA = createElement('div');\n    var elementB = cloneElement(elementA, elementA.props);\n    expect(elementB.key).toBe(null);\n    expect(elementB.ref).toBe(null);\n  });\n\n  it('should ignore undefined key and ref', function() {\n    expect(() => {\n      var element = createFactory(ComponentClass)({\n        key: '12',\n        ref: '34',\n        foo: '56',\n      });\n      var props = {\n        key: undefined,\n        ref: undefined,\n        foo: 'ef',\n      };\n      var clone = cloneElement(element, props);\n      expect(clone.type).toBe(ComponentClass);\n      expect(clone.key).toBe('12');\n      expect(clone.ref).toBe('34');\n      expect(clone.props).toEqual({foo: 'ef'});\n    }).toWarnDev('Adding a string ref \"34\" that was not created inside render method, or multiple copies of Rax are used.', {withoutStack: true});\n  });\n\n  it('should extract null key and ref', function() {\n    expect(() => {\n      var element = createFactory(ComponentClass)({\n        key: '12',\n        ref: '34',\n        foo: '56',\n      });\n      var props = {\n        key: null,\n        ref: null,\n        foo: 'ef',\n      };\n      var clone = cloneElement(element, props);\n      expect(clone.type).toBe(ComponentClass);\n      expect(clone.key).toBe('null');\n      expect(clone.ref).toBe(null);\n      expect(clone.props).toEqual({foo: 'ef'});\n    }).toWarnDev('Adding a string ref \"34\" that was not created inside render method, or multiple copies of Rax are used.', {withoutStack: true});\n  });\n});\n"
  },
  {
    "path": "packages/rax-clone-element/src/index.js",
    "content": "import { shared } from 'rax';\nimport isValidElement from 'rax-is-valid-element';\n\nconst { Host, Element, flattenChildren } = shared;\nconst RESERVED_PROPS = {\n  key: true,\n  ref: true,\n};\n\nexport default function cloneElement(element, config, ...children) {\n  if (!isValidElement(element)) {\n    throw Error('cloneElement: not a valid element.');\n  }\n\n  // Original props are copied\n  const props = Object.assign({}, element.props);\n\n  // Reserved names are extracted\n  let key = element.key;\n  let ref = element.ref;\n\n  // Owner will be preserved, unless ref is overridden\n  let owner = element._owner;\n\n  if (config) {\n    // Should reset ref and owner if has a new ref\n    if (config.ref !== undefined) {\n      ref = config.ref;\n      owner = Host.owner;\n    }\n\n    if (config.key !== undefined) {\n      key = String(config.key);\n    }\n\n    // Resolve default props\n    let defaultProps;\n    if (element.type && element.type.defaultProps) {\n      defaultProps = element.type.defaultProps;\n    }\n    // Remaining properties override existing props\n    let propName;\n    for (propName in config) {\n      if (config.hasOwnProperty(propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        if (config[propName] === undefined && defaultProps !== undefined) {\n          // Resolve default props\n          props[propName] = defaultProps[propName];\n        } else {\n          props[propName] = config[propName];\n        }\n      }\n    }\n  }\n\n  if (children.length) {\n    props.children = flattenChildren(children);\n  }\n\n  return new Element(\n    element.type,\n    key,\n    ref,\n    props,\n    owner\n  );\n};\n"
  },
  {
    "path": "packages/rax-create-class/README.md",
    "content": "# rax-create-class"
  },
  {
    "path": "packages/rax-create-class/package.json",
    "content": "{\n  \"name\": \"rax-create-class\",\n  \"version\": \"1.0.1\",\n  \"description\": \"Rax createClass\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"rax\": \"^1.0.0\",\n    \"driver-server\": \"^1.0.0\",\n    \"prop-types\": \"^15.7.2\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-create-class/src/__tests__/createClass.js",
    "content": "/* @jsx createElement */\n/* eslint react/prefer-es6-class: \"off\" */\n\nimport { createElement, render, shared } from 'rax';\nimport PropTypes from 'prop-types';\nimport ServerDriver from 'driver-server';\nimport createClass from '../';\n\nconst { Host } = shared;\n\ndescribe('createClass', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n  });\n\n  it('should copy `displayName` onto the Constructor', function() {\n    var TestComponent = createClass({\n      displayName: 'TestComponent',\n      render: function() {\n        return <div />;\n      }\n    });\n\n    expect(TestComponent.displayName).toBe('TestComponent');\n  });\n\n  it('should support statics', function() {\n    var Component = createClass({\n      statics: {\n        abc: 'def',\n        def: 0,\n        ghi: null,\n        jkl: 'mno',\n        pqr: function() {\n          return this;\n        },\n      },\n\n      render: function() {\n        return <span />;\n      },\n    });\n\n    var instance = render(<Component />);\n    expect(instance.constructor.abc).toBe('def');\n    expect(Component.abc).toBe('def');\n    expect(instance.constructor.def).toBe(0);\n    expect(Component.def).toBe(0);\n    expect(instance.constructor.ghi).toBe(null);\n    expect(Component.ghi).toBe(null);\n    expect(instance.constructor.jkl).toBe('mno');\n    expect(Component.jkl).toBe('mno');\n    expect(instance.constructor.pqr()).toBe(Component);\n    expect(Component.pqr()).toBe(Component);\n  });\n\n  it('should work with object getInitialState() return values', function() {\n    var Component = createClass({\n      getInitialState: function() {\n        return {\n          occupation: 'clown',\n        };\n      },\n      render: function() {\n        return <span />;\n      },\n    });\n\n    var instance = render(<Component />);\n    expect(instance.state.occupation).toEqual('clown');\n  });\n\n  it('renders based on context getInitialState', function() {\n    var Foo = createClass({\n      contextTypes: {\n        className: PropTypes.string,\n      },\n      getInitialState() {\n        return {className: this.context.className};\n      },\n      render() {\n        return <span className={this.state.className} />;\n      },\n    });\n\n    var Outer = createClass({\n      childContextTypes: {\n        className: PropTypes.string,\n      },\n      getChildContext() {\n        return {className: 'foo'};\n      },\n      render() {\n        return <Foo />;\n      },\n    });\n\n    var container = createNodeElement('div');\n    render(<Outer />, container);\n    expect(container.childNodes[0].attributes.class).toBe('foo');\n  });\n\n  it('should support statics in mixins', function() {\n    var Mixin = {\n      statics: {\n        foo: 'bar',\n      },\n    };\n    var Component = createClass({\n      mixins: [Mixin],\n\n      statics: {\n        abc: 'def',\n      },\n\n      render: function() {\n        return <span />;\n      },\n    });\n\n    var container = createNodeElement('div');\n    var instance = render(<Component />, container);\n\n    expect(instance.constructor.foo).toBe('bar');\n    expect(Component.foo).toBe('bar');\n    expect(instance.constructor.abc).toBe('def');\n    expect(Component.abc).toBe('def');\n  });\n\n  it('should include the mixin keys in even if their values are falsy', function() {\n    var mixin = {\n      keyWithNullValue: null,\n      randomCounter: 0,\n    };\n\n    var Component = createClass({\n      mixins: [mixin],\n      componentDidMount: function() {\n        expect(this.randomCounter).toBe(0);\n        expect(this.keyWithNullValue).toBeNull();\n      },\n      render: function() {\n        return <span />;\n      },\n    });\n\n    render(<Component />, createNodeElement('div'));\n  });\n\n  it('should work with a null getInitialState return value and a mixin', () => {\n    var Component;\n    var instance;\n\n    var Mixin = {\n      getInitialState: function() {\n        return {foo: 'bar'};\n      },\n    };\n    Component = createClass({\n      mixins: [Mixin],\n      getInitialState: function() {\n        return null;\n      },\n      render: function() {\n        return <span />;\n      },\n    });\n\n    instance = render(<Component />, createNodeElement('div'));\n    expect(instance.state).toEqual({foo: 'bar'});\n\n    // Also the other way round should work\n    var Mixin2 = {\n      getInitialState: function() {\n        return null;\n      },\n    };\n    Component = createClass({\n      mixins: [Mixin2],\n      getInitialState: function() {\n        return {foo: 'bar'};\n      },\n      render: function() {\n        return <span />;\n      },\n    });\n\n    instance = render(<Component />, createNodeElement('div'));\n    expect(instance.state).toEqual({foo: 'bar'});\n\n    // Multiple mixins should be fine too\n    Component = createClass({\n      mixins: [Mixin, Mixin2],\n      getInitialState: function() {\n        return {x: true};\n      },\n      render: function() {\n        return <span />;\n      },\n    });\n\n    instance = render(<Component />, createNodeElement('div'));\n    expect(instance.state).toEqual({foo: 'bar', x: true});\n  });\n\n  it('should have bound the mixin methods to the component', function() {\n    var mixin = {\n      mixinFunc: function() {\n        return this;\n      },\n    };\n\n    var Component = createClass({\n      mixins: [mixin],\n      componentDidMount: function() {\n        expect(this.mixinFunc()).toBe(this);\n      },\n      render: function() {\n        return <span />;\n      },\n    });\n\n    render(<Component />, createNodeElement('div'));\n  });\n\n  it('should support mixins with getInitialState()', function() {\n    var Mixin = {\n      getInitialState: function() {\n        return {mixin: true};\n      },\n    };\n    var Component = createClass({\n      mixins: [Mixin],\n      getInitialState: function() {\n        return {component: true};\n      },\n      render: function() {\n        return <span />;\n      },\n    });\n    var instance = render(<Component />, createNodeElement('div'));\n    expect(instance.state.component).toBe(true);\n    expect(instance.state.mixin).toBe(true);\n  });\n\n  it('should support merging propTypes and statics', function() {\n    var MixinA = {\n      propTypes: {\n        propA: function() {},\n      },\n      componentDidMount: function() {\n        this.props.listener('MixinA didMount');\n      },\n    };\n\n    var MixinB = {\n      mixins: [MixinA],\n      propTypes: {\n        propB: function() {},\n      },\n      componentDidMount: function() {\n        this.props.listener('MixinB didMount');\n      },\n    };\n\n    var MixinC = {\n      statics: {\n        staticC: function() {},\n      },\n      componentDidMount: function() {\n        this.props.listener('MixinC didMount');\n      },\n    };\n\n    var MixinD = {\n      propTypes: {\n        value: PropTypes.string,\n      },\n    };\n\n    var Component = createClass({\n      mixins: [MixinB, MixinC, MixinD],\n      statics: {\n        staticComponent: function() {},\n      },\n      propTypes: {\n        propComponent: function() {},\n      },\n      componentDidMount: function() {\n        this.props.listener('Component didMount');\n      },\n      render: function() {\n        return <div />;\n      },\n    });\n\n    var listener = function() {};\n    var instance = render(<Component listener={listener} />, createNodeElement('div'));\n    var instancePropTypes = instance.constructor.propTypes;\n\n    expect('propA' in instancePropTypes).toBe(true);\n    expect('propB' in instancePropTypes).toBe(true);\n    expect('propComponent' in instancePropTypes).toBe(true);\n\n    expect('staticC' in Component).toBe(true);\n    expect('staticComponent' in Component).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/rax-create-class/src/index.js",
    "content": "import { Component } from 'rax';\n\nconst AUTOBIND_BLACKLIST = {\n  render: 1,\n  shouldComponentUpdate: 1,\n  componentWillReceiveProps: 1,\n  componentWillUpdate: 1,\n  componentDidUpdate: 1,\n  componentWillMount: 1,\n  componentDidMount: 1,\n  componentWillUnmount: 1,\n  componentDidUnmount: 1\n};\n\nfunction collateMixins(mixins) {\n  let keyed = {};\n\n  for (let i = 0; i < mixins.length; i++) {\n    let mixin = mixins[i];\n    if (mixin.mixins) {\n      applyMixins(mixin, collateMixins(mixin.mixins));\n    }\n\n    for (let key in mixin) {\n      if (mixin.hasOwnProperty(key) && key !== 'mixins') {\n        (keyed[key] || (keyed[key] = [])).push(mixin[key]);\n      }\n    }\n  }\n\n  return keyed;\n}\n\nfunction flattenHooks(key, hooks) {\n  let hookType = typeof hooks[0];\n  if (hookType === 'object') {\n    // Merge objects in hooks\n    hooks.unshift({});\n    return Object.assign.apply(null, hooks);\n  } else if (hookType === 'function' && (key === 'getInitialState' || key === 'getDefaultProps' || key === 'getChildContext')) {\n    return function() {\n      let ret;\n      for (let i = 0; i < hooks.length; i++) {\n        let r = hooks[i].apply(this, arguments);\n        if (r) {\n          if (!ret) ret = {};\n          Object.assign(ret, r);\n        }\n      }\n      return ret;\n    };\n  } else {\n    return hooks[0];\n  }\n}\n\nfunction applyMixins(proto, mixins) {\n  for (let key in mixins) {\n    if (mixins.hasOwnProperty(key)) {\n      proto[key] = flattenHooks(key, mixins[key].concat(proto[key] || []));\n    }\n  }\n}\n\nfunction createReactClass(spec) {\n  class ReactClass extends Component {\n    constructor(props, context) {\n      super(props, context);\n\n      for (let methodName in this) {\n        let method = this[methodName];\n        if (typeof method === 'function' && !AUTOBIND_BLACKLIST[methodName]) {\n          this[methodName] = method.bind(this);\n        }\n      }\n\n      if (spec.getInitialState) {\n        this.state = spec.getInitialState.call(this);\n      }\n    }\n  }\n\n  if (spec.mixins) {\n    applyMixins(spec, collateMixins(spec.mixins));\n  }\n\n  Object.assign(ReactClass.prototype, spec);\n\n  if (spec.statics) {\n    Object.assign(ReactClass, spec.statics);\n  }\n\n  if (spec.propTypes) {\n    ReactClass.propTypes = spec.propTypes;\n  }\n\n  if (spec.getDefaultProps) {\n    ReactClass.defaultProps = spec.getDefaultProps();\n  }\n\n  if (spec.contextTypes) {\n    ReactClass.contextTypes = spec.contextTypes;\n  }\n\n  if (spec.childContextTypes) {\n    ReactClass.childContextTypes = spec.childContextTypes;\n  }\n\n  if (spec.displayName) {\n    ReactClass.displayName = spec.displayName;\n  }\n\n  return ReactClass;\n}\n\nexport default createReactClass;\n"
  },
  {
    "path": "packages/rax-create-factory/README.md",
    "content": "# rax-create-factory"
  },
  {
    "path": "packages/rax-create-factory/package.json",
    "content": "{\n  \"name\": \"rax-create-factory\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Rax createFactory\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"devDependencies\": {\n    \"rax\": \"^1.0.0\",\n    \"driver-server\": \"^1.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-create-factory/src/__tests__/createFactory.js",
    "content": "\n/* @jsx createElement */\n\nimport { createElement, Component, shared } from 'rax';\nimport createFactory from '../';\nimport ServerDriver from 'driver-server';\n\nconst { Host } = shared;\n\ndescribe('cloneElement', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n  });\n\n  class ComponentClass extends Component {\n    render() {\n      return <div />;\n    }\n  }\n\n  it('returns a complete element according to spec', function() {\n    let element = createFactory(ComponentClass)();\n    expect(element.type).toBe(ComponentClass);\n    expect(element.key).toBe(null);\n    expect(element.ref).toBe(null);\n    // expect(Object.isFrozen(element)).toBe(true);\n    // expect(Object.isFrozen(element.props)).toBe(true);\n    expect(element.props).toEqual({});\n  });\n\n  it('coerces the key to a string', function() {\n    let element = 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    // expect(Object.isFrozen(element)).toBe(true);\n    // expect(Object.isFrozen(element.props)).toBe(true);\n    expect(element.props).toEqual({foo: '56'});\n  });\n\n  it('merges an additional argument onto the children prop', function() {\n    let a = 1;\n    let element = createFactory(ComponentClass)({\n      children: 'text',\n    }, a);\n    expect(element.props.children).toBe(a);\n  });\n\n  it('does not override children if no rest args are provided', function() {\n    let element = createFactory(ComponentClass)({\n      children: 'text',\n    });\n    expect(element.props.children).toBe('text');\n  });\n\n  it('overrides children if null is provided as an argument', function() {\n    let element = createFactory(ComponentClass)({\n      children: 'text',\n    }, null);\n    expect(element.props.children).toBe(null);\n  });\n\n  it('merges rest arguments onto the children prop in an array', function() {\n    let a = 1;\n    let b = 2;\n    let c = 3;\n    let element = createFactory(ComponentClass)(null, a, b, c);\n    expect(element.props.children).toEqual([1, 2, 3]);\n  });\n});"
  },
  {
    "path": "packages/rax-create-factory/src/index.js",
    "content": "import { createElement } from 'rax';\n\nexport default function createFactory(type) {\n  const factory = createElement.bind(null, type);\n  // Expose the type on the factory and the prototype so that it can be\n  // easily accessed on elements. E.g. `<Foo />.type === Foo`.\n  // This should not be named `constructor` since this may not be the function\n  // that created the element, and it may not even be a constructor.\n  factory.type = type;\n  return factory;\n}\n"
  },
  {
    "path": "packages/rax-create-portal/README.md",
    "content": "# rax-create-portal"
  },
  {
    "path": "packages/rax-create-portal/package.json",
    "content": "{\n  \"name\": \"rax-create-portal\",\n  \"version\": \"1.1.0\",\n  \"description\": \"Rax createPortal\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"dependencies\": {\n    \"rax-unmount-component-at-node\": \"^1.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"rax\": \"^1.0.0\",\n    \"driver-server\": \"^1.0.0\",\n    \"driver-dom\": \"^2.1.3\",\n    \"rax-proptypes\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-create-portal/src/__tests__/createPortal.js",
    "content": "/* @jsx createElement */\n\nimport PropTypes from 'rax-proptypes';\nimport { Component, createElement, render, shared, createContext, useContext, useState } from 'rax';\nimport ServerDriver from 'driver-server';\nimport * as DriverDOM from 'driver-dom';\nimport unmountComponentAtNode from 'rax-unmount-component-at-node';\nimport createPortal from '../';\n\nconst { Host } = shared;\n\ndescribe('createPortal', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n    jest.useRealTimers();\n  });\n\n  it('should render one portal', () => {\n    const container = createNodeElement('div');\n    const portalContainer = createNodeElement('div');\n\n    render(\n      <div>{createPortal(<div>portal</div>, portalContainer)}</div>,\n      container\n    );\n\n    jest.runAllTimers();\n    expect(container.childNodes[0].tagName).toBe('DIV');\n    expect(portalContainer.childNodes[0].childNodes[0].data).toBe('portal');\n\n    unmountComponentAtNode(container);\n\n    expect(container.childNodes.length).toBe(0);\n    expect(portalContainer.childNodes.length).toBe(0);\n  });\n\n\n  it('should pass portal context when rendering subtree elsewhere', function() {\n    const container = createNodeElement('div');\n    const portalContainer = createNodeElement('div');\n\n    class Sub extends Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      render() {\n        return <div>{this.context.foo}</div>;\n      }\n    }\n\n    class Parent extends Component {\n      static childContextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      getChildContext() {\n        return {\n          foo: 'bar',\n        };\n      }\n\n      render() {\n        return createPortal(<Sub />, portalContainer);\n      }\n    }\n\n    render(<Parent />, container);\n\n    jest.runAllTimers();\n    expect(container.childNodes[0].nodeType).toBe(8);\n    expect(portalContainer.childNodes[0].childNodes[0].data).toBe('bar');\n  });\n\n  it('should update portal context if it changes due to re-render', () => {\n    const container = createNodeElement('div');\n    const portalContainer = createNodeElement('div');\n\n    class Sub extends Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n        getFoo: PropTypes.func.isRequired,\n      };\n\n      render() {\n        return <div>{this.context.foo + '-' + this.context.getFoo()}</div>;\n      }\n    }\n\n    class Parent extends Component {\n      static childContextTypes = {\n        foo: PropTypes.string.isRequired,\n        getFoo: PropTypes.func.isRequired,\n      };\n\n      getChildContext() {\n        return {\n          foo: this.props.bar,\n          getFoo: () => this.props.bar,\n        };\n      }\n\n      render() {\n        return createPortal(<Sub />, portalContainer);\n      }\n    }\n\n    render(<Parent bar=\"initial\" />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].nodeType).toBe(8);\n    expect(portalContainer.childNodes[0].childNodes[0].data).toBe('initial-initial');\n\n    render(<Parent bar=\"changed\" />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].nodeType).toBe(8);\n    expect(portalContainer.childNodes[0].childNodes[0].data).toBe('changed-changed');\n  });\n\n  it('should update portal if context or element change', () => {\n    const container = createNodeElement('div');\n    const portalContainer = createNodeElement('div');\n    let updatedCount = 0;\n\n    class Sub extends Component {\n      static contextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      render() {\n        updatedCount++;\n        return <div>{ this.context.foo || 'initial' }</div>;\n      }\n    }\n    const CacheSub = <Sub />;\n\n    class Parent extends Component {\n      static childContextTypes = {\n        foo: PropTypes.string.isRequired,\n      };\n\n      getChildContext() {\n        if (!this.props.hasContext) return null;\n        return {\n          foo: this.props.bar,\n        };\n      }\n\n      render() {\n        return createPortal(this.props.newElement ? <Sub /> : CacheSub, portalContainer);\n      }\n    }\n\n    render(<Parent />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].nodeType).toBe(8);\n    expect(portalContainer.childNodes[0].childNodes[0].data).toBe('initial');\n    expect(updatedCount).toBe(1);\n\n    // nothing can be changed\n    render(<Parent />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].nodeType).toBe(8);\n    expect(portalContainer.childNodes[0].childNodes[0].data).toBe('initial');\n    expect(updatedCount).toBe(1);\n\n    // Context change\n    render(<Parent bar=\"changed\" hasContext={true} />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].nodeType).toBe(8);\n    expect(portalContainer.childNodes[0].childNodes[0].data).toBe('changed');\n    expect(updatedCount).toBe(2);\n\n    // change context -> null\n    render(<Parent />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].nodeType).toBe(8);\n    expect(portalContainer.childNodes[0].childNodes[0].data).toBe('initial');\n    expect(updatedCount).toBe(3);\n\n    // nothing can be changed\n    render(<Parent />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].nodeType).toBe(8);\n    expect(portalContainer.childNodes[0].childNodes[0].data).toBe('initial');\n    expect(updatedCount).toBe(3);\n\n    // element change\n    render(<Parent newElement={true} />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].nodeType).toBe(8);\n    expect(portalContainer.childNodes[0].childNodes[0].data).toBe('initial');\n    expect(updatedCount).toBe(4);\n  });\n\n  it('should render correct when new context change', () => {\n    const container = createNodeElement('div');\n    const portalTarget = createNodeElement('div');\n    const Context = createContext(0);\n\n    let changeValue = null;\n    function Portal() {\n      const value = useContext(Context);\n      return <div>{value}</div>;\n    }\n\n    function App() {\n      const [value, setValue] = useState(1);\n      changeValue = setValue;\n      return (\n        <Context.Provider value={value}>\n          <div>0</div>\n          {createPortal(<Portal />, portalTarget)}\n        </Context.Provider>\n      );\n    }\n    render(<App />, container);\n    jest.runAllTimers();\n    expect(container.childNodes[0].childNodes[0].data).toBe('0');\n    expect(portalTarget.childNodes[0].childNodes[0].data).toBe('1');\n\n    changeValue(2);\n    jest.runAllTimers();\n    expect(portalTarget.childNodes[0].childNodes[0].data).toBe('2');\n  });\n\n  it('should not affect the result of hydrate', () => {\n    const container = document.createElement('div');\n    container.innerHTML = '<div class=\"container\"><div>About Rax</div><div>Docs</div></div>';\n    (document.body || document.documentElement).appendChild(container);\n\n    const portalContainer = document.createElement('div');\n    (document.body || document.documentElement).appendChild(portalContainer);\n\n    const App = () => {\n      return (\n        <div class=\"container\">\n          <div>About Rax</div>\n          {createPortal(<div>portal</div>, portalContainer)}\n        </div>\n      );\n    };\n\n    jest.useFakeTimers();\n\n    render(<App />, container, { driver: DriverDOM, hydrate: true });\n\n    jest.runAllTimers();\n\n    expect(container.childNodes[0].childNodes[1].nodeType).toBe(8); // comment;\n    expect(portalContainer.childNodes[0].childNodes[0].data).toBe('portal');\n  });\n});\n"
  },
  {
    "path": "packages/rax-create-portal/src/index.js",
    "content": "import { render, createElement, useEffect } from 'rax';\nimport unmountComponentAtNode from 'rax-unmount-component-at-node';\n\nfunction Portal(props) {\n  useEffect(() => {\n    // Nested render will cause error when hydrating, it should be trigger in useEffect.\n    render(props.element, props.container, {\n      parent: this\n    });\n  });\n\n  useEffect(() => {\n    return () => {\n      unmountComponentAtNode(props.container);\n    };\n  }, [props.container]);\n\n  return null;\n}\n\nexport default function createPortal(element, container) {\n  return createElement(Portal, {\n    element,\n    container,\n  });\n}\n"
  },
  {
    "path": "packages/rax-document/CHANGELOG.md",
    "content": "# Changelog\n\n## v0.1.6\n\n- Chore: bundle script should add `crossorigin=\"anonymous\"` default\n"
  },
  {
    "path": "packages/rax-document/README.md",
    "content": "# rax-document\n\nProvide components for building Document.\n\n## Usage\n\n```jsx\nimport { createElement } from 'rax';\nimport { Root, Data, Style, Script } from 'rax-document';\n\nexport default () => {\n  return (\n    <html>\n      <head>\n        <meta charset=\"utf-8\" />\n        <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/>\n        <title>ssr-document-demo</title>\n        <Style />\n      </head>\n      <body>\n        {/* root container */}\n        <Root />\n        {/* initial data from server side */}\n        <Data />\n        <Script />\n      </body>\n    </html>\n  );\n}\n```\n\n## Components\n\n`Style`\n\nStyles for page. Automatic analyzed from your project.\n\n`Script`\n\nScripts for page. Automatic analyzed from your project.\n\n`Root`\n\nRoot container for page. In normal Web app, it will be an empty node. In SSR project, the initial HTML will be output in this node.\n\n`Data`\n\nInitial data from server side. Required only in SSR project.\n\n`App`\n\nProvide `pageInfo` for Multi Page Application.\n\nUsage:\n\n```jsx\nimport { createElement } from 'rax';\nimport { Root, Style, Script, App} from 'rax-document';\n\nimport appJSON from '../app.json';\n\nfunction Document() {\n  return (\n    <App config={appJSON}>\n      {\n        pageInfo => <html>\n          <head>\n            <meta charset=\"utf-8\" />\n            <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover\"/>\n            <title>{pageInfo.title}</title>\n            <Style />\n          </head>\n          <body>\n            {/* root container */}\n            <Root />\n            <Script />\n          </body>\n        </html>\n      }\n    </App>\n  );\n}\n\nexport default Document;\n```\n\n"
  },
  {
    "path": "packages/rax-document/package.json",
    "content": "{\n  \"name\": \"rax-document\",\n  \"version\": \"0.1.6\",\n  \"description\": \"Provide components for building Document\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-document/src/index.js",
    "content": "import { createElement } from 'rax';\n\nfunction Root(props, context) {\n  const { __initialHtml } = context;\n\n  // comment node for ssr parse root node position\n  if (process.env.__IS_SERVER__) {\n    return [\n      { __html: '<!--__BEFORE_ROOT__-->' },\n      <div id=\"root\" key=\"root\" dangerouslySetInnerHTML={{ __html: __initialHtml || '' }} />,\n      { __html: '<!--__AFTER_ROOT__-->' }\n    ];\n  }\n  return <div id=\"root\" key=\"root\" dangerouslySetInnerHTML={{ __html: __initialHtml || '' }} />;\n}\n\nfunction Manifest(props, context) {\n  const { __manifests, __pagePath } = context;\n\n  if (Array.isArray(__manifests)) {\n    const manifest = __manifests.find((item) => {\n      return item.path === __pagePath;\n    });\n\n    // manifest json type: https://developer.mozilla.org/en-US/docs/Web/Manifest#Deploying_a_manifest_with_the_link_tag\n    if (manifest && manifest.data) {\n      return (\n        <script type=\"application/manifest+json\" dangerouslySetInnerHTML={{__html: JSON.stringify(manifest.data)}} />\n      );\n    }\n  }\n\n  return null;\n}\n\nfunction Data(props, context) {\n  const { __initialData } = context;\n\n  if (__initialData) {\n    return <script data-from=\"server\" dangerouslySetInnerHTML={{__html: 'window.__INITIAL_DATA__=' + __initialData}} />;\n  }\n\n  return null;\n}\n\n// Named by role rather than implementationm, so component name are `Style` rather than `Styles`.\nfunction Style(props, context) {\n  const { __styles = [] } = context;\n\n  return __styles.map((src, index) => <link {...props} rel=\"stylesheet\" href={src} key={`style_${index}`} />);\n}\n\nfunction Script(props, context) {\n  const { __scripts = [] } = context;\n\n  // props such as type can be passed to script tag\n  // script default crossorigin value is anonymous\n  return __scripts.map(\n    (src, index) => <script crossorigin=\"anonymous\" {...props} src={src} key={`script_${index}`}>\n      {/* self-closing script element will not work in HTML */}\n    </script>\n  );\n}\n\nfunction App(props, context) {\n  const config = props.config || {};\n  const routes = config.routes || [];\n\n  const pagePath = context.__pagePath;\n\n  const currentPageInfo = routes.find((route) => {\n    return route.path == pagePath;\n  });\n\n  const consumer = Array.isArray(props.children) ? props.children[0] : props.children;\n\n  if (typeof consumer === 'function') {\n    return consumer(currentPageInfo);\n  }\n\n  return props.children;\n}\n\nexport {\n  Root,\n  Data,\n  Style,\n  Script,\n  App,\n  Manifest\n};\n"
  },
  {
    "path": "packages/rax-dom/README.md",
    "content": "# rax-dom\n"
  },
  {
    "path": "packages/rax-dom/package.json",
    "content": "{\n  \"name\": \"rax-dom\",\n  \"version\": \"1.0.2-0\",\n  \"description\": \"Rax DOM render\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"dependencies\": {\n    \"driver-dom\": \"2.0.1-0\",\n    \"rax-hydrate\": \"^1.0.0\",\n    \"rax-unmount-component-at-node\": \"^1.0.0\",\n    \"rax-find-dom-node\": \"^1.0.0\",\n    \"rax-create-portal\": \"^1.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-dom/src/index.js",
    "content": "import { render } from 'rax';\nimport * as DriverDOM from 'driver-dom';\nimport hydrate from 'rax-hydrate';\nimport unmountComponentAtNode from 'rax-unmount-component-at-node';\nimport findDOMNode from 'rax-find-dom-node';\nimport createPortal from 'rax-create-portal';\n\nfunction normalizeEventName(node, eventName, props) {\n  const tagName = node.tagName.toLowerCase();\n\n  if (\n    eventName === 'change' &&\n    (tagName === 'textarea' ||\n      tagName === 'input' && (!props.type || props.type === 'text' || props.type === 'password'))\n  ) {\n    eventName = 'input';\n  } else if (eventName === 'doubleclick') {\n    eventName = 'dblclick';\n  }\n  return eventName;\n}\n\nconst driver = Object.assign({}, DriverDOM, {\n  addEventListener(node, eventName, eventHandler, props) {\n    eventName = normalizeEventName(node, eventName, props);\n    return DriverDOM.addEventListener(node, eventName, eventHandler, props);\n  },\n  removeEventListener(node, eventName, eventHandler, props) {\n    eventName = normalizeEventName(node, eventName, props);\n    return DriverDOM.removeEventListener(node, eventName, eventHandler, props);\n  },\n});\n\nconst domRender = (element, container, callback) => render(\n  element,\n  container,\n  {\n    driver,\n  },\n  callback,\n);\n\nexport {\n  domRender as render,\n  hydrate,\n  unmountComponentAtNode,\n  findDOMNode,\n  createPortal,\n};\n\nexport default {\n  render: domRender,\n  hydrate,\n  unmountComponentAtNode,\n  findDOMNode,\n  createPortal,\n};\n"
  },
  {
    "path": "packages/rax-find-dom-node/README.md",
    "content": "# rax-find-dom-node"
  },
  {
    "path": "packages/rax-find-dom-node/package.json",
    "content": "{\n  \"name\": \"rax-find-dom-node\",\n  \"version\": \"1.0.1\",\n  \"description\": \"Rax findDOMNode\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"dependencies\": {\n    \"rax-get-element-by-id\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"rax\": \"^1.0.0\",\n    \"universal-env\": \"^3.0.0\",\n    \"driver-server\": \"^1.0.0\",\n    \"rax-unmount-component-at-node\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-find-dom-node/src/__tests__/findDOMNode.js",
    "content": "/* @jsx createElement */\n\nimport findDOMNode from '../';\nimport {Component, createElement, render, shared} from 'rax';\nimport ServerDriver from 'driver-server';\nimport unmountComponentAtNode from 'rax-unmount-component-at-node';\n\nconst { Host } = shared;\n\ndescribe('findDOMNode', () => {\n  function createNodeElement(tagName) {\n    return {\n      nodeType: 1,\n      tagName: tagName.toUpperCase(),\n      attributes: {},\n      style: {},\n      childNodes: [],\n      parentNode: null\n    };\n  }\n\n  beforeEach(function() {\n    Host.driver = ServerDriver;\n  });\n\n  afterEach(function() {\n    Host.driver = null;\n  });\n\n  it('findDOMNode with null', () => {\n    let node = findDOMNode(null);\n    expect(node).toBeNull();\n  });\n\n  it('findDOMNode with node', () => {\n    let node = findDOMNode({\n      ownerDocument: {}\n    });\n\n    expect(node).toEqual({\n      ownerDocument: {}\n    });\n\n    let node2 = findDOMNode({\n      nodeType: 1\n    });\n\n    expect(node2).toEqual({\n      nodeType: 1\n    });\n  });\n\n  it('findDOMNode with native component', () => {\n    let node = findDOMNode({\n      _nativeNode: {}\n    });\n\n    expect(node).toEqual({});\n  });\n\n\n  it('findDOMNode with composite component', () => {\n    let node = findDOMNode({\n      _internal: {\n        _renderedComponent: {\n          _nativeNode: {\n            nodeType: 1\n          }\n        }\n      },\n      render() {}\n    });\n\n    expect(node).toEqual({\n      nodeType: 1\n    });\n\n    let node2 = findDOMNode({\n      _internal: {\n        _renderedComponent: {\n          _renderedComponent: {\n            _nativeNode: {\n              nodeType: 2\n            }\n          }\n        }\n      },\n      render() {}\n    });\n\n    expect(node2).toEqual({\n      nodeType: 2\n    });\n\n    let node3 = findDOMNode({\n      _internal: {\n        _renderedComponent: {\n          _renderedComponent: null\n        }\n      },\n      render() {}\n    });\n\n    expect(node3).toEqual(null);\n  });\n\n  it('findDOMNode should reject random objects', function() {\n    expect(function() {\n      findDOMNode({foo: 'bar'});\n    }).toThrowError(\n      'findDOMNode: find by neither component nor DOM node.'\n    );\n  });\n\n  it('findDOMNode should reject unmounted objects with render func', function() {\n    class Foo extends Component {\n      render() {\n        return <div />;\n      }\n    }\n\n    let container = createNodeElement('div');\n    var inst = render(<Foo />, container);\n    unmountComponentAtNode(container);\n\n    expect(() => findDOMNode(inst)).toThrowError(\n      'findDOMNode: find on an unmounted component.'\n    );\n  });\n\n  it('findDOMNode should not throw an error when called within a component that is not mounted', function() {\n    class Bar extends Component {\n      componentWillMount() {\n        expect(findDOMNode(this)).toBeNull();\n      }\n\n      render() {\n        return <div />;\n      }\n    }\n\n    expect(() => render(<Bar />)).not.toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/rax-find-dom-node/src/__tests__/findDOMNode.weex.js",
    "content": "/* @jsx createElement */\n\nimport {shared} from 'rax';\nimport ServerDriver from 'driver-server';\nimport findDOMNode from '../';\nimport getElementById from 'rax-get-element-by-id';\n\n// mock weex env\njest.mock('rax-get-element-by-id', () => ({\n  __esModule: true,\n  default: (id) => {\n    const { shared } = require('rax');\n    const { Host } = shared;\n    return Host.driver && Host.driver.getElementById(id);\n  }\n}));\n\nconst { Host } = shared;\nHost.driver = ServerDriver;\n\ndescribe('findDOMNode', () => {\n  it('getElementById with id', () => {\n    let mockFn = jest.fn();\n    Host.driver = {\n      getElementById: mockFn,\n    };\n    getElementById('id');\n    expect(mockFn).toBeCalledWith('id');\n  });\n\n  it('findDOMNode with id', () => {\n    let mockFn = jest.fn();\n    Host.driver = {\n      getElementById: mockFn,\n    };\n    findDOMNode('id');\n    expect(mockFn).toBeCalledWith('id');\n  });\n});"
  },
  {
    "path": "packages/rax-find-dom-node/src/index.js",
    "content": "import getElementById from 'rax-get-element-by-id';\n\nfunction findDOMNode(instance) {\n  if (instance == null) {\n    return null;\n  }\n\n  // If a native node, weex may not export ownerDocument property\n  if (instance.ownerDocument || instance.nodeType) {\n    return instance;\n  }\n\n  // Native component\n  if (instance._nativeNode) {\n    return instance._nativeNode;\n  }\n\n  if (typeof instance == 'string') {\n    return getElementById(instance);\n  }\n\n  if (typeof instance.render !== 'function') {\n    throw new Error('findDOMNode: find by neither component nor DOM node.');\n  }\n\n  // Composite component\n  let internal = instance._internal;\n\n  if (internal) {\n    while (!internal._nativeNode) {\n      internal = internal._renderedComponent;\n      // If not mounted\n      if (internal == null) {\n        return null;\n      }\n    }\n    return internal._nativeNode;\n  } else {\n    throw new Error('findDOMNode: find on an unmounted component.');\n  }\n}\n\nexport default findDOMNode;\n"
  },
  {
    "path": "packages/rax-get-element-by-id/CHANGELOG.md",
    "content": "## CHANGELOG\n\n### 1.0.1\n\n- chore: bump `universal-env` dep version.\n"
  },
  {
    "path": "packages/rax-get-element-by-id/README.md",
    "content": "# rax-get-element-by-id"
  },
  {
    "path": "packages/rax-get-element-by-id/package.json",
    "content": "{\n  \"name\": \"rax-get-element-by-id\",\n  \"version\": \"1.0.1\",\n  \"description\": \"Rax getElementById\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"dependencies\": {\n    \"universal-env\": \"^3.0.0\",\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-get-element-by-id/src/index.js",
    "content": "/* global wx */\nimport { isWeex, isWeb } from 'universal-env';\nimport { shared } from 'rax';\n\nexport default function getElementById(id) {\n  if (isWeex) {\n    return shared.Host.driver.getElementById(id);\n  } else if (isWeb) {\n    return document.getElementById(id);\n  } else if (typeof my == 'object') {\n    return my.createSelectorQuery().select('#' + id);\n  } else if (typeof wx == 'object') {\n    return wx.createSelectorQuery().select('#' + id);\n  }\n}"
  },
  {
    "path": "packages/rax-hydrate/README.md",
    "content": "# rax-hydrate\n"
  },
  {
    "path": "packages/rax-hydrate/package.json",
    "content": "{\n  \"name\": \"rax-hydrate\",\n  \"version\": \"1.0.1\",\n  \"description\": \"Rax hydration render\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"dependencies\": {\n    \"driver-dom\": \"^1.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-hydrate/src/index.js",
    "content": "import { render } from 'rax';\nimport * as DriverDOM from 'driver-dom';\n\nexport default (element, container, callback) => {\n  render(element, container, {\n    hydrate: true,\n    driver: DriverDOM\n  }, callback);\n};\n"
  },
  {
    "path": "packages/rax-is-valid-element/README.md",
    "content": "# rax-is-valid-element"
  },
  {
    "path": "packages/rax-is-valid-element/package.json",
    "content": "{\n  \"name\": \"rax-is-valid-element\",\n  \"version\": \"1.0.1\",\n  \"description\": \"Rax isValidElement\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-is-valid-element/src/__tests__/isValidElement.js",
    "content": "/* @jsx createElement */\n\nimport isValidElement from '../';\n\ndescribe('isValidElement', () => {\n  it('Return type of isValidElement should be boolean type', () => {\n    expect(isValidElement()).toBe(false);\n    expect(isValidElement(null)).toBe(false);\n    expect(isValidElement({})).toBe(false);\n    expect(isValidElement({type: 'div'})).toBe(false);\n\n    expect(isValidElement({\n      type: 'div',\n      props: {}\n    })).toBe(true);\n    expect(isValidElement({\n      type: 'div',\n      props: {\n        style: {}\n      }\n    })).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/rax-is-valid-element/src/index.js",
    "content": "export default function isValidElement(object) {\n  return !!(typeof object === 'object' && object !== null && object.type && object.props);\n}\n"
  },
  {
    "path": "packages/rax-proptypes/README.md",
    "content": "# rax-proptypes"
  },
  {
    "path": "packages/rax-proptypes/package.json",
    "content": "{\n  \"name\": \"rax-proptypes\",\n  \"version\": \"2.0.0\",\n  \"description\": \"Rax Proptypes\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"dependencies\": {\n    \"prop-types\": \"^15.7.2\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-proptypes/src/__tests__/proptypes.js",
    "content": "/* @jsx createElement */\n\nimport PropTypes from '../';\n\ndescribe('PropTypes', () => {\n  it('Primitive types should be defined', () => {\n    expect(PropTypes.array).toBeDefined();\n    expect(PropTypes.bool).toBeDefined();\n    expect(PropTypes.func).toBeDefined();\n    expect(PropTypes.number).toBeDefined();\n    expect(PropTypes.object).toBeDefined();\n    expect(PropTypes.string).toBeDefined();\n    expect(PropTypes.symbol).toBeDefined();\n  });\n\n  it('Custom types should be defined', () => {\n    expect(PropTypes.node).toBeDefined();\n    expect(PropTypes.element).toBeDefined();\n    expect(PropTypes.instanceOf).toBeDefined();\n    expect(PropTypes.oneOf).toBeDefined();\n    expect(PropTypes.oneOfType).toBeDefined();\n    expect(PropTypes.arrayOf).toBeDefined();\n    expect(PropTypes.objectOf).toBeDefined();\n    expect(PropTypes.shape).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "packages/rax-proptypes/src/index.js",
    "content": "/*\n * Export prop-types directly.\n */\n\nimport PropTypes from 'prop-types';\n\nexport default PropTypes;\n"
  },
  {
    "path": "packages/rax-redux/CHANGELOG.md",
    "content": "## Changelog\n\n## v1.0.1\n\n- Chore: add `@babel/runtime` as dependency\n"
  },
  {
    "path": "packages/rax-redux/README.md",
    "content": "# rax-redux [![npm](https://img.shields.io/npm/v/rax-redux.svg)](https://www.npmjs.com/package/rax-redux)\n\n\n### Install\n\n```sh\nnpm install --save rax-redux\n```\n\n### Usage\n\n```js\nimport { createElement, render } from 'rax';\nimport { Provider } from 'rax-redux';\n\nimport store from './store';\nimport App from './App';\n\nrender(\n  <Provider store={store}>\n    <App />\n  </Provider>\n);\n```\n\n### API\n\nSome with react-redux v7.1 https://react-redux.js.org\n"
  },
  {
    "path": "packages/rax-redux/package.json",
    "content": "{\n  \"name\": \"rax-redux\",\n  \"version\": \"1.0.1\",\n  \"description\": \"Official Rax bindings for Redux.\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"dependencies\": {\n    \"invariant\": \"^2.2.4\",\n    \"@babel/runtime\": \"^7.14.6\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\",\n    \"redux\": \"^2.0.0 || ^3.0.0 || ^4.0.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"rax\": {\n      \"optional\": true\n    }\n  },\n  \"devDependencies\": {\n    \"rax-test-renderer\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-redux/src/components/Context.js",
    "content": "import { createContext } from 'rax';\n\nexport const ReactReduxContext = createContext(null);\n\nexport default ReactReduxContext;\n"
  },
  {
    "path": "packages/rax-redux/src/components/Provider.js",
    "content": "import { createElement, useMemo, useEffect } from 'rax';\nimport { ReactReduxContext } from './Context';\nimport Subscription from '../utils/Subscription';\n\nfunction Provider({ store, context, children }) {\n  const contextValue = useMemo(() => {\n    const subscription = new Subscription(store);\n    subscription.onStateChange = subscription.notifyNestedSubs;\n    return {\n      store,\n      subscription\n    };\n  }, [store]);\n\n  const previousState = useMemo(() => store.getState(), [store]);\n\n  useEffect(() => {\n    const { subscription } = contextValue;\n    subscription.trySubscribe();\n\n    if (previousState !== store.getState()) {\n      subscription.notifyNestedSubs();\n    }\n    return () => {\n      subscription.tryUnsubscribe();\n      subscription.onStateChange = null;\n    };\n  }, [contextValue, previousState]);\n\n  const Context = context || ReactReduxContext;\n\n  return <Context.Provider value={contextValue}>{children}</Context.Provider>;\n}\n\n// Provider.propTypes = {\n//   store: PropTypes.shape({\n//     subscribe: PropTypes.func.isRequired,\n//     dispatch: PropTypes.func.isRequired,\n//     getState: PropTypes.func.isRequired\n//   }),\n//   context: PropTypes.object,\n//   children: PropTypes.any\n// }\n\nexport default Provider;\n"
  },
  {
    "path": "packages/rax-redux/src/components/connectAdvanced.js",
    "content": "import invariant from 'invariant';\nimport {\n  createElement,\n  forwardRef as raxforwardRef,\n  memo as raxMemo,\n  useContext,\n  useMemo,\n  useEffect,\n  useLayoutEffect,\n  useRef,\n  useReducer\n} from 'rax';\nimport Subscription from '../utils/Subscription';\nimport hoistNonReactStatics from '../utils/hoistNonReactStatics';\nimport { ReactReduxContext } from './Context';\nimport isValidElementType from '../utils/isValidElementType';\n\n\n// Define some constant arrays just to avoid re-creating these\nconst EMPTY_ARRAY = [];\nconst NO_SUBSCRIPTION_ARRAY = [null, null];\n\nconst stringifyComponent = Comp => {\n  try {\n    return JSON.stringify(Comp);\n  } catch (err) {\n    return String(Comp);\n  }\n};\n\nfunction storeStateUpdatesReducer(state, action) {\n  const [, updateCount] = state;\n  return [action.payload, updateCount + 1];\n}\n\nconst initStateUpdates = () => [null, 0];\n\n// React currently throws a warning when using useLayoutEffect on the server.\n// To get around it, we can conditionally useEffect on the server (no-op) and\n// useLayoutEffect in the browser. We need useLayoutEffect because we want\n// `connect` to perform sync updates to a ref to save the latest props after\n// a render is actually committed to the DOM.\nconst useIsomorphicLayoutEffect =\n  typeof window !== 'undefined' &&\n  typeof window.document !== 'undefined' &&\n  typeof window.document.createElement !== 'undefined'\n    ? useLayoutEffect\n    : useEffect;\n\nexport default function connectAdvanced(\n  /*\n    selectorFactory is a func that is responsible for returning the selector function used to\n    compute new props from state, props, and dispatch. For example:\n\n      export default connectAdvanced((dispatch, options) => (state, props) => ({\n        thing: state.things[props.thingId],\n        saveThing: fields => dispatch(actionCreators.saveThing(props.thingId, fields)),\n      }))(YourComponent)\n\n    Access to dispatch is provided to the factory so selectorFactories can bind actionCreators\n    outside of their selector as an optimization. Options passed to connectAdvanced are passed to\n    the selectorFactory, along with displayName and WrappedComponent, as the second argument.\n\n    Note that selectorFactory is responsible for all caching/memoization of inbound and outbound\n    props. Do not use connectAdvanced directly without memoizing results between calls to your\n    selector, otherwise the Connect component will re-render on every state or props change.\n  */\n  selectorFactory,\n  // options object:\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    getDisplayName = name => `ConnectAdvanced(${name})`,\n\n    // shown in error messages\n    // probably overridden by wrapper functions such as connect()\n    methodName = 'connectAdvanced',\n\n    // REMOVED: 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    renderCountProp = undefined,\n\n    // determines whether this HOC subscribes to store changes\n    shouldHandleStateChanges = true,\n\n    // REMOVED: the key of props/context to get the store\n    storeKey = 'store',\n\n    // REMOVED: expose the wrapped component via refs\n    withRef = false,\n\n    // use React's forwardRef to expose a ref of the wrapped component\n    forwardRef = false,\n\n    // the context consumer to use\n    context = ReactReduxContext,\n\n    // additional options are passed through to the selectorFactory\n    ...connectOptions\n  } = {}\n) {\n  invariant(\n    renderCountProp === undefined,\n    'renderCountProp is removed. render counting is built into the latest React Dev Tools profiling extension'\n  );\n\n  invariant(\n    !withRef,\n    'withRef is removed. To access the wrapped instance, use a ref on the connected component'\n  );\n\n  const customStoreWarningMessage =\n    'To use a custom Redux store for specific components, create a custom React context with ' +\n    \"React.createContext(), and pass the context object to React Redux's Provider and specific components\" +\n    ' like: <Provider context={MyContext}><ConnectedComponent context={MyContext} /></Provider>. ' +\n    'You may also pass a {context : MyContext} option to connect';\n\n  invariant(\n    storeKey === 'store',\n    'storeKey has been removed and does not do anything. ' +\n      customStoreWarningMessage\n  );\n\n  const Context = context;\n\n  return function wrapWithConnect(WrappedComponent) {\n    if (process.env.NODE_ENV !== 'production') {\n      invariant(\n        isValidElementType(WrappedComponent),\n        'You must pass a component to the function returned by ' +\n          `${methodName}. Instead received ${stringifyComponent(\n            WrappedComponent\n          )}`\n      );\n    }\n\n    const wrappedComponentName =\n      WrappedComponent.displayName || WrappedComponent.name || 'Component';\n\n    const displayName = getDisplayName(wrappedComponentName);\n\n    const selectorFactoryOptions = {\n      ...connectOptions,\n      getDisplayName,\n      methodName,\n      renderCountProp,\n      shouldHandleStateChanges,\n      storeKey,\n      displayName,\n      wrappedComponentName,\n      WrappedComponent\n    };\n\n    const { pure } = connectOptions;\n\n    function createChildSelector(store) {\n      return selectorFactory(store.dispatch, selectorFactoryOptions);\n    }\n\n    // If we aren't running in \"pure\" mode, we don't want to memoize values.\n    // To avoid conditionally calling hooks, we fall back to a tiny wrapper\n    // that just executes the given callback immediately.\n    const usePureOnlyMemo = pure ? useMemo : callback => callback();\n\n    function ConnectFunction(props) {\n      const [propsContext, forwardedRef, wrapperProps] = useMemo(() => {\n        // Distinguish between actual \"data\" props that were passed to the wrapper component,\n        // and values needed to control behavior (forwarded refs, alternate context instances).\n        // To maintain the wrapperProps object reference, memoize this destructuring.\n        const { forwardedRef, ...wrapperProps } = props;\n        return [props.context, forwardedRef, wrapperProps];\n      }, [props]);\n\n      const ContextToUse = useMemo(() => {\n        // Users may optionally pass in a custom context instance to use instead of our ReactReduxContext.\n        // Memoize the check that determines which context instance we should use.\n        return propsContext &&\n          propsContext.Consumer\n          // && isContextConsumer(<propsContext.Consumer />)\n          ? propsContext\n          : Context;\n      }, [propsContext, Context]);\n\n      // Retrieve the store and ancestor subscription via context, if available\n      const contextValue = useContext(ContextToUse);\n\n      // The store _must_ exist as either a prop or in context\n      const didStoreComeFromProps = Boolean(props.store);\n      const didStoreComeFromContext =\n        Boolean(contextValue) && Boolean(contextValue.store);\n\n      invariant(\n        didStoreComeFromProps || didStoreComeFromContext,\n        'Could not find \"store\" in the context of ' +\n          `\"${displayName}\". Either wrap the root component in a <Provider>, ` +\n          'or pass a custom React context provider to <Provider> and the corresponding ' +\n          `React context consumer to ${displayName} in connect options.`\n      );\n\n      const store = props.store || contextValue.store;\n\n      const childPropsSelector = useMemo(() => {\n        // The child props selector needs the store reference as an input.\n        // Re-create this selector whenever the store changes.\n        return createChildSelector(store);\n      }, [store]);\n\n      const [subscription, notifyNestedSubs] = useMemo(() => {\n        if (!shouldHandleStateChanges) return NO_SUBSCRIPTION_ARRAY;\n\n        // This Subscription'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 subscription = new Subscription(\n          store,\n          didStoreComeFromProps ? null : contextValue.subscription\n        );\n\n        // `notifyNestedSubs` is duplicated to handle the case where the component is unmounted in\n        // the middle of the notification loop, where `subscription` will then be null. This can\n        // probably be avoided if Subscription's listeners logic is changed to not call listeners\n        // that have been unsubscribed in the  middle of the notification loop.\n        const notifyNestedSubs = subscription.notifyNestedSubs.bind(\n          subscription\n        );\n\n        return [subscription, notifyNestedSubs];\n      }, [store, didStoreComeFromProps, contextValue]);\n\n      // Determine what {store, subscription} value should be put into nested context, if necessary,\n      // and memoize that value to avoid unnecessary context updates.\n      const overriddenContextValue = useMemo(() => {\n        if (didStoreComeFromProps) {\n          // This component is directly subscribed to a store from props.\n          // We don't want descendants reading from this store - pass down whatever\n          // the existing context value is from the nearest connected ancestor.\n          return contextValue;\n        }\n\n        // Otherwise, put this component's subscription instance into context, so that\n        // connected descendants won't update until after this component is done\n        return {\n          ...contextValue,\n          subscription\n        };\n      }, [didStoreComeFromProps, contextValue, subscription]);\n\n      // We need to force this wrapper component to re-render whenever a Redux store update\n      // causes a change to the calculated child component props (or we caught an error in mapState)\n      const [\n        [previousStateUpdateResult],\n        forceComponentUpdateDispatch\n      ] = useReducer(storeStateUpdatesReducer, EMPTY_ARRAY, initStateUpdates);\n\n      // Propagate any mapState/mapDispatch errors upwards\n      if (previousStateUpdateResult && previousStateUpdateResult.error) {\n        throw previousStateUpdateResult.error;\n      }\n\n      // Set up refs to coordinate values between the subscription effect and the render logic\n      const lastChildProps = useRef();\n      const lastWrapperProps = useRef(wrapperProps);\n      const childPropsFromStoreUpdate = useRef();\n      const renderIsScheduled = useRef(false);\n\n      const actualChildProps = usePureOnlyMemo(() => {\n        // Tricky logic here:\n        // - This render may have been triggered by a Redux store update that produced new child props\n        // - However, we may have gotten new wrapper props after that\n        // If we have new child props, and the same wrapper props, we know we should use the new child props as-is.\n        // But, if we have new wrapper props, those might change the child props, so we have to recalculate things.\n        // So, we'll use the child props from store update only if the wrapper props are the same as last time.\n        if (\n          childPropsFromStoreUpdate.current &&\n          wrapperProps === lastWrapperProps.current\n        ) {\n          return childPropsFromStoreUpdate.current;\n        }\n\n        // TODO We're reading the store directly in render() here. Bad idea?\n        // This will likely cause Bad Things (TM) to happen in Concurrent Mode.\n        // Note that we do this because on renders _not_ caused by store updates, we need the latest store state\n        // to determine what the child props should be.\n        return childPropsSelector(store.getState(), wrapperProps);\n      }, [store, previousStateUpdateResult, wrapperProps]);\n\n      // We need this to execute synchronously every time we re-render. However, React warns\n      // about useLayoutEffect in SSR, so we try to detect environment and fall back to\n      // just useEffect instead to avoid the warning, since neither will run anyway.\n      useIsomorphicLayoutEffect(() => {\n        // We want to capture the wrapper props and child props we used for later comparisons\n        lastWrapperProps.current = wrapperProps;\n        lastChildProps.current = actualChildProps;\n        renderIsScheduled.current = false;\n\n        // If the render was from a store update, clear out that reference and cascade the subscriber update\n        if (childPropsFromStoreUpdate.current) {\n          childPropsFromStoreUpdate.current = null;\n          notifyNestedSubs();\n        }\n      });\n\n      // Our re-subscribe logic only runs when the store/subscription setup changes\n      useIsomorphicLayoutEffect(() => {\n        // If we're not subscribed to the store, nothing to do here\n        if (!shouldHandleStateChanges) return;\n\n        // Capture values for checking if and when this component unmounts\n        let didUnsubscribe = false;\n        let lastThrownError = null;\n\n        // We'll run this callback every time a store subscription update propagates to this component\n        const checkForUpdates = () => {\n          if (didUnsubscribe) {\n            // Don't run stale listeners.\n            // Redux doesn't guarantee unsubscriptions happen until next dispatch.\n            return;\n          }\n\n          const latestStoreState = store.getState();\n\n          let newChildProps, error;\n          try {\n            // Actually run the selector with the most recent store state and wrapper props\n            // to determine what the child props should be\n            newChildProps = childPropsSelector(\n              latestStoreState,\n              lastWrapperProps.current\n            );\n          } catch (e) {\n            error = e;\n            lastThrownError = e;\n          }\n\n          if (!error) {\n            lastThrownError = null;\n          }\n\n          // If the child props haven't changed, nothing to do here - cascade the subscription update\n          if (newChildProps === lastChildProps.current) {\n            if (!renderIsScheduled.current) {\n              notifyNestedSubs();\n            }\n          } else {\n            // Save references to the new child props.  Note that we track the \"child props from store update\"\n            // as a ref instead of a useState/useReducer because we need a way to determine if that value has\n            // been processed.  If this went into useState/useReducer, we couldn't clear out the value without\n            // forcing another re-render, which we don't want.\n            lastChildProps.current = newChildProps;\n            childPropsFromStoreUpdate.current = newChildProps;\n            renderIsScheduled.current = true;\n\n            // If the child props _did_ change (or we caught an error), this wrapper component needs to re-render\n            forceComponentUpdateDispatch({\n              type: 'STORE_UPDATED',\n              payload: {\n                error\n              }\n            });\n          }\n        };\n\n        // Actually subscribe to the nearest connected ancestor (or store)\n        subscription.onStateChange = checkForUpdates;\n        subscription.trySubscribe();\n\n        // Pull data from the store after first render in case the store has\n        // changed since we began.\n        checkForUpdates();\n\n        const unsubscribeWrapper = () => {\n          didUnsubscribe = true;\n          subscription.tryUnsubscribe();\n          subscription.onStateChange = null;\n\n          if (lastThrownError) {\n            // It's possible that we caught an error due to a bad mapState function, but the\n            // parent re-rendered without this component and we're about to unmount.\n            // This shouldn't happen as long as we do top-down subscriptions correctly, but\n            // if we ever do those wrong, this throw will surface the error in our tests.\n            // In that case, throw the error from here so it doesn't get lost.\n            throw lastThrownError;\n          }\n        };\n\n        return unsubscribeWrapper;\n      }, [store, subscription, childPropsSelector]);\n\n      // Now that all that's done, we can finally try to actually render the child component.\n      // We memoize the elements for the rendered child component as an optimization.\n      const renderedWrappedComponent = useMemo(\n        () => <WrappedComponent {...actualChildProps} ref={forwardedRef} />,\n        [forwardedRef, WrappedComponent, actualChildProps]\n      );\n\n      // If React sees the exact same element reference as last time, it bails out of re-rendering\n      // that child, same as if it was wrapped in React.memo() or returned false from shouldComponentUpdate.\n      const renderedChild = useMemo(() => {\n        if (shouldHandleStateChanges) {\n          // If this component is subscribed to store updates, we need to pass its own\n          // subscription instance down to our descendants. That means rendering the same\n          // Context instance, and putting a different value into the context.\n          return (\n            <ContextToUse.Provider value={overriddenContextValue}>\n              {renderedWrappedComponent}\n            </ContextToUse.Provider>\n          );\n        }\n\n        return renderedWrappedComponent;\n      }, [ContextToUse, renderedWrappedComponent, overriddenContextValue]);\n\n      return renderedChild;\n    }\n\n    // If we're in \"pure\" mode, ensure our wrapper component only re-renders when incoming props have changed.\n    const Connect = pure ? raxMemo(ConnectFunction) : ConnectFunction;\n\n    Connect.WrappedComponent = WrappedComponent;\n    Connect.displayName = displayName;\n\n    if (forwardRef) {\n      const forwarded = raxforwardRef(function forwardConnectRef(\n        props,\n        ref\n      ) {\n        return <Connect {...props} forwardedRef={ref} />;\n      });\n\n      forwarded.displayName = displayName;\n      forwarded.WrappedComponent = WrappedComponent;\n      return hoistNonReactStatics(forwarded, WrappedComponent);\n    }\n\n    return hoistNonReactStatics(Connect, WrappedComponent);\n  };\n}\n"
  },
  {
    "path": "packages/rax-redux/src/connect/connect.js",
    "content": "import connectAdvanced from '../components/connectAdvanced';\nimport shallowEqual from '../utils/shallowEqual';\nimport defaultMapDispatchToPropsFactories from './mapDispatchToProps';\nimport defaultMapStateToPropsFactories from './mapStateToProps';\nimport defaultMergePropsFactories from './mergeProps';\nimport defaultSelectorFactory from './selectorFactory';\n\n/*\n  connect is a facade over connectAdvanced. It turns its args into a compatible\n  selectorFactory, which has the signature:\n\n    (dispatch, options) => (nextState, nextOwnProps) => nextFinalProps\n\n  connect passes its args to connectAdvanced as options, which will in turn pass them to\n  selectorFactory each time a Connect component instance is instantiated or hot reloaded.\n\n  selectorFactory returns a final props selector from its mapStateToProps,\n  mapStateToPropsFactories, mapDispatchToProps, mapDispatchToPropsFactories, mergeProps,\n  mergePropsFactories, and pure args.\n\n  The resulting final props selector is called by the Connect component instance whenever\n  it receives new props or store state.\n */\n\nfunction match(arg, factories, name) {\n  for (let i = factories.length - 1; i >= 0; i--) {\n    const result = factories[i](arg);\n    if (result) return result;\n  }\n\n  return (dispatch, options) => {\n    throw new Error(\n      `Invalid value of type ${typeof arg} for ${name} argument when connecting component ${\n        options.wrappedComponentName\n      }.`\n    );\n  };\n}\n\nfunction strictEqual(a, b) {\n  return a === b;\n}\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 function createConnect({\n  connectHOC = connectAdvanced,\n  mapStateToPropsFactories = defaultMapStateToPropsFactories,\n  mapDispatchToPropsFactories = defaultMapDispatchToPropsFactories,\n  mergePropsFactories = defaultMergePropsFactories,\n  selectorFactory = defaultSelectorFactory\n} = {}) {\n  return function connect(\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, {\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: Boolean(mapStateToProps),\n\n      // passed through to selectorFactory\n      initMapStateToProps,\n      initMapDispatchToProps,\n      initMergeProps,\n      pure,\n      areStatesEqual,\n      areOwnPropsEqual,\n      areStatePropsEqual,\n      areMergedPropsEqual,\n\n      // any extra options args can override defaults of connect or connectAdvanced\n      ...extraOptions\n    });\n  };\n}\n\nexport default createConnect();\n"
  },
  {
    "path": "packages/rax-redux/src/connect/mapDispatchToProps.js",
    "content": "import { bindActionCreators } from 'redux';\nimport { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps';\n\nexport function whenMapDispatchToPropsIsFunction(mapDispatchToProps) {\n  return typeof mapDispatchToProps === 'function'\n    ? wrapMapToPropsFunc(mapDispatchToProps, 'mapDispatchToProps')\n    : undefined;\n}\n\nexport function whenMapDispatchToPropsIsMissing(mapDispatchToProps) {\n  return !mapDispatchToProps\n    ? wrapMapToPropsConstant(dispatch => ({ dispatch }))\n    : undefined;\n}\n\nexport function whenMapDispatchToPropsIsObject(mapDispatchToProps) {\n  return mapDispatchToProps && typeof mapDispatchToProps === 'object'\n    ? wrapMapToPropsConstant(dispatch =>\n      bindActionCreators(mapDispatchToProps, dispatch)\n    )\n    : undefined;\n}\n\nexport default [\n  whenMapDispatchToPropsIsFunction,\n  whenMapDispatchToPropsIsMissing,\n  whenMapDispatchToPropsIsObject\n];\n"
  },
  {
    "path": "packages/rax-redux/src/connect/mapStateToProps.js",
    "content": "import { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps';\n\nexport function whenMapStateToPropsIsFunction(mapStateToProps) {\n  return typeof mapStateToProps === 'function'\n    ? wrapMapToPropsFunc(mapStateToProps, 'mapStateToProps')\n    : undefined;\n}\n\nexport function whenMapStateToPropsIsMissing(mapStateToProps) {\n  return !mapStateToProps ? wrapMapToPropsConstant(() => ({})) : undefined;\n}\n\nexport default [whenMapStateToPropsIsFunction, whenMapStateToPropsIsMissing];\n"
  },
  {
    "path": "packages/rax-redux/src/connect/mergeProps.js",
    "content": "import verifyPlainObject from '../utils/verifyPlainObject';\n\nexport function defaultMergeProps(stateProps, dispatchProps, ownProps) {\n  return { ...ownProps, ...stateProps, ...dispatchProps };\n}\n\nexport function wrapMergePropsFunc(mergeProps) {\n  return function initMergePropsProxy(\n    dispatch,\n    { displayName, pure, areMergedPropsEqual }\n  ) {\n    let hasRunOnce = false;\n    let mergedProps;\n\n    return function mergePropsProxy(stateProps, dispatchProps, ownProps) {\n      const nextMergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n\n      if (hasRunOnce) {\n        if (!pure || !areMergedPropsEqual(nextMergedProps, mergedProps))\n          mergedProps = nextMergedProps;\n      } else {\n        hasRunOnce = true;\n        mergedProps = nextMergedProps;\n\n        if (process.env.NODE_ENV !== 'production')\n          verifyPlainObject(mergedProps, displayName, 'mergeProps');\n      }\n\n      return mergedProps;\n    };\n  };\n}\n\nexport function whenMergePropsIsFunction(mergeProps) {\n  return typeof mergeProps === 'function'\n    ? wrapMergePropsFunc(mergeProps)\n    : undefined;\n}\n\nexport function whenMergePropsIsOmitted(mergeProps) {\n  return !mergeProps ? () => defaultMergeProps : undefined;\n}\n\nexport default [whenMergePropsIsFunction, whenMergePropsIsOmitted];\n"
  },
  {
    "path": "packages/rax-redux/src/connect/selectorFactory.js",
    "content": "import verifySubselectors from './verifySubselectors';\n\nexport function impureFinalPropsSelectorFactory(\n  mapStateToProps,\n  mapDispatchToProps,\n  mergeProps,\n  dispatch\n) {\n  return function impureFinalPropsSelector(state, ownProps) {\n    return mergeProps(\n      mapStateToProps(state, ownProps),\n      mapDispatchToProps(dispatch, ownProps),\n      ownProps\n    );\n  };\n}\n\nexport function 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  function 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  function handleNewPropsAndNewState() {\n    stateProps = mapStateToProps(state, ownProps);\n\n    if (mapDispatchToProps.dependsOnOwnProps)\n      dispatchProps = mapDispatchToProps(dispatch, ownProps);\n\n    mergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n    return mergedProps;\n  }\n\n  function handleNewProps() {\n    if (mapStateToProps.dependsOnOwnProps)\n      stateProps = mapStateToProps(state, ownProps);\n\n    if (mapDispatchToProps.dependsOnOwnProps)\n      dispatchProps = mapDispatchToProps(dispatch, ownProps);\n\n    mergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n    return mergedProps;\n  }\n\n  function 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    return mergedProps;\n  }\n\n  function 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) return handleNewPropsAndNewState();\n    if (propsChanged) return handleNewProps();\n    if (stateChanged) return handleNewState();\n    return mergedProps;\n  }\n\n  return function pureFinalPropsSelector(nextState, nextOwnProps) {\n    return hasRunAtLeastOnce\n      ? handleSubsequentCalls(nextState, nextOwnProps)\n      : handleFirstCall(nextState, nextOwnProps);\n  };\n}\n\n// TODO: Add more comments\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.\n\nexport default function finalPropsSelectorFactory(\n  dispatch,\n  { initMapStateToProps, initMapDispatchToProps, initMergeProps, ...options }\n) {\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/rax-redux/src/connect/verifySubselectors.js",
    "content": "import warning from '../utils/warning';\n\nfunction verify(selector, methodName, displayName) {\n  if (!selector) {\n    throw new Error(`Unexpected value for ${methodName} in ${displayName}.`);\n  } else if (\n    methodName === 'mapStateToProps' ||\n    methodName === 'mapDispatchToProps'\n  ) {\n    if (!Object.prototype.hasOwnProperty.call(selector, 'dependsOnOwnProps')) {\n      warning(\n        `The selector for ${methodName} of ${displayName} did not specify a value for dependsOnOwnProps.`\n      );\n    }\n  }\n}\n\nexport default function 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/rax-redux/src/connect/wrapMapToProps.js",
    "content": "import verifyPlainObject from '../utils/verifyPlainObject';\n\nexport function wrapMapToPropsConstant(getConstant) {\n  return function initConstantSelector(dispatch, options) {\n    const constant = getConstant(dispatch, options);\n\n    function constantSelector() {\n      return constant;\n    }\n    constantSelector.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 function getDependsOnOwnProps(mapToProps) {\n  return mapToProps.dependsOnOwnProps !== null &&\n    mapToProps.dependsOnOwnProps !== undefined\n    ? Boolean(mapToProps.dependsOnOwnProps)\n    : mapToProps.length !== 1;\n}\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 function wrapMapToPropsFunc(mapToProps, methodName) {\n  return function initProxySelector(dispatch, { displayName }) {\n    const proxy = function mapToPropsProxy(stateOrDispatch, ownProps) {\n      return proxy.dependsOnOwnProps\n        ? proxy.mapToProps(stateOrDispatch, ownProps)\n        : proxy.mapToProps(stateOrDispatch);\n    };\n\n    // allow detectFactoryAndVerify to get ownProps\n    proxy.dependsOnOwnProps = true;\n\n    proxy.mapToProps = function detectFactoryAndVerify(\n      stateOrDispatch,\n      ownProps\n    ) {\n      proxy.mapToProps = mapToProps;\n      proxy.dependsOnOwnProps = getDependsOnOwnProps(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      return props;\n    };\n\n    return proxy;\n  };\n}\n"
  },
  {
    "path": "packages/rax-redux/src/hooks/useDispatch.js",
    "content": "import { ReactReduxContext } from '../components/Context';\nimport { useStore as useDefaultStore, createStoreHook } from './useStore';\n\n/**\n * Hook factory, which creates a `useDispatch` hook bound to a given context.\n *\n * @param {Function} [context=ReactReduxContext] Context passed to your `<Provider>`.\n * @returns {Function} A `useDispatch` hook bound to the specified context.\n */\nexport function createDispatchHook(context = ReactReduxContext) {\n  const useStore =\n    context === ReactReduxContext ? useDefaultStore : createStoreHook(context);\n  return function useDispatch() {\n    const store = useStore();\n    return store.dispatch;\n  };\n}\n\n/**\n * A hook to access the redux `dispatch` function.\n *\n * @returns {any|function} redux store's `dispatch` function\n *\n * @example\n *\n * import React, { useCallback } from 'react'\n * import { useDispatch } from 'react-redux'\n *\n * export const CounterComponent = ({ value }) => {\n *   const dispatch = useDispatch()\n *   const increaseCounter = useCallback(() => dispatch({ type: 'increase-counter' }), [])\n *   return (\n *     <div>\n *       <span>{value}</span>\n *       <button onClick={increaseCounter}>Increase counter</button>\n *     </div>\n *   )\n * }\n */\nexport const useDispatch = createDispatchHook();\n"
  },
  {
    "path": "packages/rax-redux/src/hooks/useReduxContext.js",
    "content": "import { useContext } from 'rax';\nimport invariant from 'invariant';\nimport { ReactReduxContext } from '../components/Context';\n\n/**\n * A hook to access the value of the `ReactReduxContext`. This is a low-level\n * hook that you should usually not need to call directly.\n *\n * @returns {any} the value of the `ReactReduxContext`\n *\n * @example\n *\n * import React from 'react'\n * import { useReduxContext } from 'react-redux'\n *\n * export const CounterComponent = ({ value }) => {\n *   const { store } = useReduxContext()\n *   return <div>{store.getState()}</div>\n * }\n */\nexport function useReduxContext() {\n  const contextValue = useContext(ReactReduxContext);\n\n  invariant(\n    contextValue,\n    'could not find react-redux context value; please ensure the component is wrapped in a <Provider>'\n  );\n\n  return contextValue;\n}\n"
  },
  {
    "path": "packages/rax-redux/src/hooks/useSelector.js",
    "content": "import {\n  useReducer,\n  useRef,\n  useEffect,\n  useMemo,\n  useLayoutEffect,\n  useContext\n} from 'rax';\nimport invariant from 'invariant';\nimport { useReduxContext as useDefaultReduxContext } from './useReduxContext';\nimport Subscription from '../utils/Subscription';\nimport { ReactReduxContext } from '../components/Context';\n\n// React currently throws a warning when using useLayoutEffect on the server.\n// To get around it, we can conditionally useEffect on the server (no-op) and\n// useLayoutEffect in the browser. We need useLayoutEffect to ensure the store\n// subscription callback always has the selector from the latest render commit\n// available, otherwise a store update may happen between render and the effect,\n// which may cause missed updates; we also must ensure the store subscription\n// is created synchronously, otherwise a store update may occur before the\n// subscription is created and an inconsistent state may be observed\nconst useIsomorphicLayoutEffect =\n  typeof window !== 'undefined' &&\n  typeof window.document !== 'undefined' &&\n  typeof window.document.createElement !== 'undefined'\n    ? useLayoutEffect\n    : useEffect;\n\nconst refEquality = (a, b) => a === b;\n\nfunction useSelectorWithStoreAndSubscription(\n  selector,\n  equalityFn,\n  store,\n  contextSub\n) {\n  const [, forceRender] = useReducer(s => s + 1, 0);\n\n  const subscription = useMemo(() => new Subscription(store, contextSub), [\n    store,\n    contextSub\n  ]);\n\n  const latestSubscriptionCallbackError = useRef();\n  const latestSelector = useRef();\n  const latestSelectedState = useRef();\n\n  let selectedState;\n\n  try {\n    if (\n      selector !== latestSelector.current ||\n      latestSubscriptionCallbackError.current\n    ) {\n      selectedState = selector(store.getState());\n    } else {\n      selectedState = latestSelectedState.current;\n    }\n  } catch (err) {\n    let errorMessage = `An error occurred while selecting the store state: ${err.message}.`;\n\n    if (latestSubscriptionCallbackError.current) {\n      errorMessage += `\\nThe error may be correlated with this previous error:\\n${latestSubscriptionCallbackError.current.stack}\\n\\nOriginal stack trace:`;\n    }\n\n    throw new Error(errorMessage);\n  }\n\n  useIsomorphicLayoutEffect(() => {\n    latestSelector.current = selector;\n    latestSelectedState.current = selectedState;\n    latestSubscriptionCallbackError.current = undefined;\n  });\n\n  useIsomorphicLayoutEffect(() => {\n    function checkForUpdates() {\n      try {\n        const newSelectedState = latestSelector.current(store.getState());\n\n        if (equalityFn(newSelectedState, latestSelectedState.current)) {\n          return;\n        }\n\n        latestSelectedState.current = newSelectedState;\n      } catch (err) {\n        // we ignore all errors here, since when the component\n        // is re-rendered, the selectors are called again, and\n        // will throw again, if neither props nor store state\n        // changed\n        latestSubscriptionCallbackError.current = err;\n      }\n\n      forceRender({});\n    }\n\n    subscription.onStateChange = checkForUpdates;\n    subscription.trySubscribe();\n\n    checkForUpdates();\n\n    return () => subscription.tryUnsubscribe();\n  }, [store, subscription]);\n\n  return selectedState;\n}\n\n/**\n * Hook factory, which creates a `useSelector` hook bound to a given context.\n *\n * @param {Function} [context=ReactReduxContext] Context passed to your `<Provider>`.\n * @returns {Function} A `useSelector` hook bound to the specified context.\n */\nexport function createSelectorHook(context = ReactReduxContext) {\n  const useReduxContext =\n    context === ReactReduxContext\n      ? useDefaultReduxContext\n      : () => useContext(context);\n  return function useSelector(selector, equalityFn = refEquality) {\n    invariant(selector, 'You must pass a selector to useSelectors');\n\n    const { store, subscription: contextSub } = useReduxContext();\n\n    return useSelectorWithStoreAndSubscription(\n      selector,\n      equalityFn,\n      store,\n      contextSub\n    );\n  };\n}\n\n/**\n * A hook to access the redux store's state. This hook takes a selector function\n * as an argument. The selector is called with the store state.\n *\n * This hook takes an optional equality comparison function as the second parameter\n * that allows you to customize the way the selected state is compared to determine\n * whether the component needs to be re-rendered.\n *\n * @param {Function} selector the selector function\n * @param {Function=} equalityFn the function that will be used to determine equality\n *\n * @returns {any} the selected state\n *\n * @example\n *\n * import React from 'react'\n * import { useSelector } from 'react-redux'\n *\n * export const CounterComponent = () => {\n *   const counter = useSelector(state => state.counter)\n *   return <div>{counter}</div>\n * }\n */\nexport const useSelector = createSelectorHook();\n"
  },
  {
    "path": "packages/rax-redux/src/hooks/useStore.js",
    "content": "import { useContext } from 'rax';\nimport { ReactReduxContext } from '../components/Context';\nimport { useReduxContext as useDefaultReduxContext } from './useReduxContext';\n\n/**\n * Hook factory, which creates a `useStore` hook bound to a given context.\n *\n * @param {Function} [context=ReactReduxContext] Context passed to your `<Provider>`.\n * @returns {Function} A `useStore` hook bound to the specified context.\n */\nexport function createStoreHook(context = ReactReduxContext) {\n  const useReduxContext =\n    context === ReactReduxContext\n      ? useDefaultReduxContext\n      : () => useContext(context);\n  return function useStore() {\n    const { store } = useReduxContext();\n    return store;\n  };\n}\n\n/**\n * A hook to access the redux store.\n *\n * @returns {any} the redux store\n *\n * @example\n *\n * import React from 'react'\n * import { useStore } from 'react-redux'\n *\n * export const ExampleComponent = () => {\n *   const store = useStore()\n *   return <div>{store.getState()}</div>\n * }\n */\nexport const useStore = createStoreHook();\n"
  },
  {
    "path": "packages/rax-redux/src/index.js",
    "content": "import Provider from './components/Provider';\nimport connectAdvanced from './components/connectAdvanced';\nimport { ReactReduxContext } from './components/Context';\nimport connect from './connect/connect';\n\nimport { useDispatch, createDispatchHook } from './hooks/useDispatch';\nimport { useSelector, createSelectorHook } from './hooks/useSelector';\nimport { useStore, createStoreHook } from './hooks/useStore';\nimport { getBatch } from './utils/batch';\n\n// For other renderers besides ReactDOM and React Native, use the default noop batch function\nimport shallowEqual from './utils/shallowEqual';\n\nconst batch = getBatch();\n\nexport {\n  Provider,\n  connectAdvanced,\n  ReactReduxContext,\n  connect,\n  batch,\n  useDispatch,\n  createDispatchHook,\n  useSelector,\n  createSelectorHook,\n  useStore,\n  createStoreHook,\n  shallowEqual\n};\n"
  },
  {
    "path": "packages/rax-redux/src/utils/Subscription.js",
    "content": "import { getBatch } from './batch';\n\n// encapsulates the subscription logic for connecting a component to the redux store, as\n// well as nesting subscriptions of descendant components, so that we can ensure the\n// ancestor components re-render before descendants\n\nconst CLEARED = null;\nconst nullListeners = { notify() {} };\n\nfunction createListenerCollection() {\n  const batch = getBatch();\n  // the current/next pattern is copied from redux's createStore code.\n  // TODO: refactor+expose that code to be reusable here?\n  let current = [];\n  let next = [];\n\n  return {\n    clear() {\n      next = CLEARED;\n      current = CLEARED;\n    },\n\n    notify() {\n      const listeners = current = next;\n      batch(() => {\n        for (let i = 0; i < listeners.length; i++) {\n          listeners[i]();\n        }\n      });\n    },\n\n    get() {\n      return next;\n    },\n\n    subscribe(listener) {\n      let isSubscribed = true;\n      if (next === current) next = current.slice();\n      next.push(listener);\n\n      return function unsubscribe() {\n        if (!isSubscribed || current === CLEARED) return;\n        isSubscribed = false;\n\n        if (next === current) next = current.slice();\n        next.splice(next.indexOf(listener), 1);\n      };\n    }\n  };\n}\n\nexport default class Subscription {\n  constructor(store, parentSub) {\n    this.store = store;\n    this.parentSub = parentSub;\n    this.unsubscribe = null;\n    this.listeners = nullListeners;\n\n    this.handleChangeWrapper = this.handleChangeWrapper.bind(this);\n  }\n\n  addNestedSub(listener) {\n    this.trySubscribe();\n    return this.listeners.subscribe(listener);\n  }\n\n  notifyNestedSubs() {\n    this.listeners.notify();\n  }\n\n  handleChangeWrapper() {\n    if (this.onStateChange) {\n      this.onStateChange();\n    }\n  }\n\n  isSubscribed() {\n    return Boolean(this.unsubscribe);\n  }\n\n  trySubscribe() {\n    if (!this.unsubscribe) {\n      this.unsubscribe = this.parentSub\n        ? this.parentSub.addNestedSub(this.handleChangeWrapper)\n        : this.store.subscribe(this.handleChangeWrapper);\n\n      this.listeners = createListenerCollection();\n    }\n  }\n\n  tryUnsubscribe() {\n    if (this.unsubscribe) {\n      this.unsubscribe();\n      this.unsubscribe = null;\n      this.listeners.clear();\n      this.listeners = nullListeners;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rax-redux/src/utils/batch.js",
    "content": "// Default to a dummy \"batch\" implementation that just runs the callback\nfunction defaultNoopBatch(callback) {\n  callback();\n}\n\nlet batch = defaultNoopBatch;\n\n// Allow injecting another batching function later\nexport const setBatch = newBatch => batch = newBatch;\n\n// Supply a getter just to skip dealing with ESM bindings\nexport const getBatch = () => batch;\n"
  },
  {
    "path": "packages/rax-redux/src/utils/hoistNonReactStatics.js",
    "content": "// Simple version of https://github.com/mridgway/hoist-non-react-statics/blob/master/src/index.js\n\nconst REACT_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  propTypes: true,\n  type: true\n};\n\nconst 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 default function hoistNonReactStatics(targetComponent, sourceComponent) {\n  if (typeof sourceComponent !== 'string') { // don't hoist over string (html) components\n    let keys = Object.getOwnPropertyNames(sourceComponent);\n\n    for (let i = 0; i < keys.length; ++i) {\n      const key = keys[i];\n      if (!KNOWN_STATICS[key] &&\n          !REACT_STATICS[key] &&\n          !targetComponent[key]\n      ) {\n        targetComponent[key] = sourceComponent[key];\n      }\n    }\n  }\n  return targetComponent;\n}\n"
  },
  {
    "path": "packages/rax-redux/src/utils/isPlainObject.js",
    "content": "/**\r\n * @param {any} obj The object to inspect.\r\n * @returns {boolean} True if the argument appears to be a plain object.\r\n */\r\nexport default function isPlainObject(obj) {\r\n  if (typeof obj !== 'object' || obj === null) return false;\r\n\r\n  let proto = Object.getPrototypeOf(obj);\r\n  if (proto === null) return true;\r\n\r\n  let baseProto = proto;\r\n  while (Object.getPrototypeOf(baseProto) !== null) {\r\n    baseProto = Object.getPrototypeOf(baseProto);\r\n  }\r\n\r\n  return proto === baseProto;\r\n}\r\n"
  },
  {
    "path": "packages/rax-redux/src/utils/isValidElementType.js",
    "content": "export default function isValidElementType(type) {\n  return (\n    typeof type === 'string' ||\n    typeof type === 'function' ||\n    typeof type === 'object' && type !== null\n  );\n}"
  },
  {
    "path": "packages/rax-redux/src/utils/shallowEqual.js",
    "content": "const hasOwn = Object.prototype.hasOwnProperty;\n\nfunction is(x, y) {\n  if (x === y) {\n    return x !== 0 || y !== 0 || 1 / x === 1 / y;\n  } else {\n    return x !== x && y !== y;\n  }\n}\n\nexport default function shallowEqual(objA, objB) {\n  if (is(objA, objB)) return true;\n\n  if (\n    typeof objA !== 'object' ||\n    objA === null ||\n    typeof objB !== 'object' ||\n    objB === null\n  ) {\n    return false;\n  }\n\n  const keysA = Object.keys(objA);\n  const keysB = Object.keys(objB);\n\n  if (keysA.length !== keysB.length) return false;\n\n  for (let i = 0; i < keysA.length; i++) {\n    if (!hasOwn.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {\n      return false;\n    }\n  }\n\n  return true;\n}\n"
  },
  {
    "path": "packages/rax-redux/src/utils/verifyPlainObject.js",
    "content": "import isPlainObject from './isPlainObject';\nimport warning from './warning';\n\nexport default function verifyPlainObject(value, displayName, methodName) {\n  if (!isPlainObject(value)) {\n    warning(\n      `${methodName}() in ${displayName} must return a plain object. Instead received ${value}.`\n    );\n  }\n}\n"
  },
  {
    "path": "packages/rax-redux/src/utils/warning.js",
    "content": "/**\n * Prints a warning in the console if it exists.\n *\n * @param {String} message The warning message.\n * @returns {void}\n */\nexport default function warning(message) {\n  /* eslint-disable no-console */\n  if (typeof console !== 'undefined' && typeof console.error === 'function') {\n    console.error(message);\n  }\n  /* eslint-enable no-console */\n  try {\n    // This error was thrown as a convenience so that if you enable\n    // \"break on all exceptions\" in your console,\n    // it would pause the execution at this line.\n    throw new Error(message);\n    /* eslint-disable no-empty */\n  } catch (e) {}\n  /* eslint-enable no-empty */\n}\n"
  },
  {
    "path": "packages/rax-redux/src/utils/wrapActionCreators.js",
    "content": "import { bindActionCreators } from 'redux';\n\nexport default function wrapActionCreators(actionCreators) {\n  return dispatch => bindActionCreators(actionCreators, dispatch);\n}\n"
  },
  {
    "path": "packages/rax-server/README.md",
    "content": "# rax-server\n\n### Install\n\n```bash\nnpm install rax-server --save\n```\n\n### Usage\n\n```js\nconst http = require('http');\nconst RaxServer = require('rax-server');\nconst PORT = 8080;\nconst server = new RaxServer({\n  // ...\n});\n\nconst app = new http.createServer((req, res) => {\n  if (req.pathname === '/index') {\n    server.render(req, res, {\n      page: 'index'\n    });\n  } else {\n    // ...\n  }\n});\n\napp.listen(PORT, () => {\n  console.log(`SSR running on port ${PORT}`);\n});\n```\n\n### API\n\n#### new RaxServer(options)\n\noptions:\n* document\n  * component\n* shell（optional）\n  * component\n* pages\n  * [pageName]\n    * title\n    * component: component for page\n    * template: template for page（optional）\n    * style: styles for page\n    * scripts: scripts for page\n* renderOpts: config for rax-server-renderer\n\n```js\nconst { readFileSync } = require('fs');\nconst express = require('express');\nconst RaxServer = require('rax-server');\n\nconst PORT = 8080;\nconst app = express();\n\nconst options = {\n  document: {\n    component: require('./dist/server/document.js'),\n  },\n  shell: {\n    component: require('./dist/server/shell.js'),\n  },\n  pages: {\n    index: {\n      title: 'Index',\n      component: require('./dist/server/index.js'),\n      styles: ['./client/index.css'],\n      scripts: ['./client/index.js']\n    },\n    bar: {\n      component: require('./dsit2/server/bar.js')\n    }\n  }\n};\n\nconst server = new RaxServer(options);\n\napp.get('/', (req, res) => {\n  server.render(req, res, {\n    page: 'index'\n  });\n});\n\napp.get('/foo/bar/baz', (req, res) => {\n  server.render(req, res, {\n    page: 'bar'\n  });\n});\n\napp.listen(PORT, () => {\n  console.log(`app listening on port ${PORT}`);\n});\n```\n\n#### server.render(req, res[, options])\n\noptions:\n * page\n * pathname\n * query\n * component\n * styles\n * scripts\n * title\n\n```js\nserver.render(req, res, {\n  page: 'index'\n});\n```\n\n#### server.renderToHTML(req, res[, options])\n\n```js\nconst html = await server.renderToHTML(req, res, {\n  page: 'index'\n});\n```\n\n### Use with frameworks\n\neg. express\n\n```js\nconst express = require('express');\nconst RaxServer = require('rax-server');\n\nconst PORT = 8080;\nconst app = express();\n\nconst server = new RaxServer({\n  // ...\n});\n\napp.get('/index', (req, res) => {\n  server.render(req, res, {\n    page: 'index'\n  });\n});\n\napp.listen(PORT, () => {\n  console.log(`app listening on port ${PORT}`);\n});\n```\n"
  },
  {
    "path": "packages/rax-server/index.js",
    "content": "const url = require('url');\nconst qs = require('querystring');\nconst { createElement } = require('rax');\nconst renderer = require('rax-server-renderer');\nconst { Document, Error: _Error} = require('rax-pwa');\n\nmodule.exports = class Server {\n  constructor(options = {}) {\n    const {\n      pages,\n      ...baseConfig\n    } = options;\n\n    this.pagesConfig = pages;\n    this.baseConfig = baseConfig;\n  }\n\n  async render(req, res, options) {\n    const html = await this.renderToHTML(req, res, options);\n\n    res.setHeader('Content-Type', 'text/html; charset=utf-8');\n    res.send(html);\n  }\n\n  async renderToHTML(req, res, options = {}) {\n    const {\n      page,\n    } = options;\n\n    const baseConfig = this.baseConfig || {};\n    const pagesConfig = this.pagesConfig || {};\n\n    try {\n      const pageConfig = pagesConfig[page] || {};\n\n      return renderToHTML(req, res, {\n        ...baseConfig,\n        ...pageConfig,\n        ...options\n      });\n    } catch (err) {\n      res.statusCode = err.code === 'ENOENT' ? '404' : '500';\n      this.logError(err);\n      const errorPageConfig = pagesConfig.error || {};\n\n      return renderToHTML(req, res, {\n        err,\n        component: _Error,\n        ...baseConfig,\n        ...errorPageConfig,\n        ...options\n      });\n    }\n  }\n\n  logError(err) {\n    console.log(err);\n  }\n};\n\nfunction getParsedUrl(req, pathname, query) {\n  if (!pathname || !query) {\n    const parsedUrl = url.parse(req.url);\n\n    pathname = pathname || parsedUrl.pathname;\n    query = query || qs.parse(parsedUrl.query);\n  }\n\n  return {\n    pathname,\n    query\n  };\n}\n\nclass PageNotFoundError extends Error {\n  constructor(page) {\n    this.message = `Cannot find module for page: ${page}`;\n    this.code = 'ENOENT';\n  }\n}\n\nasync function renderToHTML(req, res, options) {\n  const {\n    err,\n    page,\n    pathname,\n    query,\n    title,\n    component,\n    styles = [],\n    scripts = [],\n    document,\n    shell,\n    renderOpts\n  } = options;\n\n  if (!component) {\n    throw new PageNotFoundError(page);\n  }\n\n  const parsedUrl = getParsedUrl(req, pathname, query);\n  const ctx = { req, res, ...parsedUrl, err };\n\n  let pageData;\n  let pageHtml;\n\n  if (shell && shell.component) {\n    const result = await renderShell({\n      ctx,\n      shell,\n      component,\n      renderOpts\n    });\n    pageData = result.data;\n    pageHtml = result.html;\n  } else {\n    pageData = await getInitialProps(component, ctx);\n    const pageElement = createElement(component, pageData);\n    pageHtml = renderer.renderToString(pageElement, renderOpts);\n  }\n\n  const documentComponent = document.component || Document;\n  const pageTitle = title || document.title;\n  const documentData = await getInitialProps(documentComponent, ctx);\n  const documentElement = createElement(documentComponent, {\n    title: pageTitle,\n    pageHtml,\n    pageData: JSON.stringify(pageData),\n    styles,\n    scripts,\n    ...documentData\n  });\n\n  const html = '<!doctype html>' + renderer.renderToString(documentElement, renderOpts);\n\n  return html;\n}\n\nasync function renderShell(options) {\n  const {\n    ctx,\n    shell,\n    component,\n    renderOpts\n  } = options;\n\n  const shellComponent = shell.component;\n  const data = await getInitialProps(shellComponent, {\n    ...ctx,\n    Component: component\n  });\n\n  const shellElement = createElement(shellComponent, {\n    ...data,\n    Component: component\n  });\n  const html = renderer.renderToString(shellElement, renderOpts);\n\n  return {\n    data,\n    html\n  };\n}\n\nasync function getInitialProps(Component, ctx) {\n  if (!Component.getInitialProps) return {};\n\n  const props = await Component.getInitialProps(ctx);\n\n  if (!props || typeof props !== 'object') {\n    const message = `\"getInitialProps()\" should resolve to an object. But found \"${props}\" instead.`;\n    throw new Error(message);\n  }\n\n  return props;\n}"
  },
  {
    "path": "packages/rax-server/package.json",
    "content": "{\n  \"name\": \"rax-server\",\n  \"version\": \"1.0.1\",\n  \"description\": \"Rax server.\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"rax\": \"^1.0.0\"\n  },\n  \"dependencies\": {\n    \"path-to-regexp\": \"^3.0.0\",\n    \"rax-pwa\": \"^1.0.0\",\n    \"rax-server-renderer\": \"^1.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-server-renderer/CHANGELOG.md",
    "content": "## Changelog\n\n### v1.4.1\n\n- Bump version\n\n### v1.4.0\n\n- Use `style-unit` convert `rpx`\n"
  },
  {
    "path": "packages/rax-server-renderer/README.md",
    "content": "# rax-server-renderer [![npm](https://img.shields.io/npm/v/rax-server-renderer.svg)](https://www.npmjs.com/package/rax-server-renderer) [![Dependency Status](https://david-dm.org/alibaba/rax.svg?path=packages/rax-server-renderer)](https://david-dm.org/alibaba/rax.svg?path=packages/rax-server-renderer) [![Known Vulnerabilities](https://snyk.io/test/npm/rax-server-renderer/badge.svg)](https://snyk.io/test/npm/rax-server-renderer)\n\n> Rax renderer for server-side render.\n\n## Install\n\n```sh\n$ npm install --save rax-server-renderer\n```\n\n## Usage\n\n```jsx\nimport {createElement, Component} from 'rax';\nimport renderer from 'rax-server-renderer';\n\nclass MyComponent extends Component {\n  render() {\n    return <div>Hello World</div>;\n  }\n}\n\nrenderer.renderToString(<MyComponent />);\n```"
  },
  {
    "path": "packages/rax-server-renderer/package.json",
    "content": "{\n  \"name\": \"rax-server-renderer\",\n  \"version\": \"1.4.1\",\n  \"description\": \"Rax renderer for server-side render.\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  },\n  \"dependencies\": {\n    \"style-unit\": \"^3.0.0\"\n  },\n  \"devDependencies\": {\n    \"prop-types\": \"^15.7.2\",\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-server-renderer/src/CSSProperty.js",
    "content": "const TRUE = true;\n\n/**\n * CSS properties which accept numbers but are not in units of \"px\".\n */\nexport const UNITLESS_NUMBER_PROPS = {\n  animationIterationCount: TRUE,\n  borderImageOutset: TRUE,\n  borderImageSlice: TRUE,\n  borderImageWidth: TRUE,\n  boxFlex: TRUE,\n  boxFlexGroup: TRUE,\n  boxOrdinalGroup: TRUE,\n  columnCount: TRUE,\n  columns: TRUE,\n  flex: TRUE,\n  flexGrow: TRUE,\n  flexPositive: TRUE,\n  flexShrink: TRUE,\n  flexNegative: TRUE,\n  flexOrder: TRUE,\n  gridArea: TRUE,\n  gridRow: TRUE,\n  gridRowEnd: TRUE,\n  gridRowSpan: TRUE,\n  gridRowStart: TRUE,\n  gridColumn: TRUE,\n  gridColumnEnd: TRUE,\n  gridColumnSpan: TRUE,\n  gridColumnStart: TRUE,\n  fontWeight: TRUE,\n  lineClamp: TRUE,\n  lineHeight: TRUE,\n  opacity: TRUE,\n  order: TRUE,\n  orphans: TRUE,\n  tabSize: TRUE,\n  widows: TRUE,\n  zIndex: TRUE,\n  zoom: TRUE,\n\n  // SVG-related properties\n  fillOpacity: TRUE,\n  floodOpacity: TRUE,\n  stopOpacity: TRUE,\n  strokeDasharray: TRUE,\n  strokeDashoffset: TRUE,\n  strokeMiterlimit: TRUE,\n  strokeOpacity: TRUE,\n  strokeWidth: TRUE,\n};\n\n/**\n * @param {string} prefix vendor-specific prefix, eg: Webkit\n * @param {string} key style name, eg: transitionDuration\n * @return {string} style name prefixed with `prefix`, properly camelCased, eg:\n * WebkitTransitionDuration\n */\nfunction prefixKey(prefix, key) {\n  return prefix + key.charAt(0).toUpperCase() + key.substring(1);\n}\n\n/**\n * Support style names that may come passed in prefixed by adding permutations\n * of vendor prefixes.\n */\nconst prefixes = ['Webkit', 'ms', 'Moz', 'O'];\n\n// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an\n// infinite loop, because it iterates over the newly added props too.\nObject.keys(UNITLESS_NUMBER_PROPS).forEach(function(prop) {\n  prefixes.forEach(function(prefix) {\n    UNITLESS_NUMBER_PROPS[prefixKey(prefix, prop)] = UNITLESS_NUMBER_PROPS[prop];\n  });\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/attributes.js",
    "content": "/* @jsx createElement */\n\nimport {createElement} from 'rax';\nimport {renderToString} from '../index';\n\ndescribe('renderToString', () => {\n  describe('property to attribute mapping', function() {\n    describe('string properties', function() {\n      it('simple numbers ', () => {\n        function MyComponent() {\n          return <div width={30} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div width=\"30\"></div>');\n      });\n\n      it('simple strings ', () => {\n        function MyComponent() {\n          return <div width={'30'} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div width=\"30\"></div>');\n      });\n\n      it('no string prop with true value', () => {\n        function MyComponent() {\n          return <a href={true} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a></a>');\n      });\n\n      it('no string prop with false value', () => {\n        function MyComponent() {\n          return <a href={false} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a></a>');\n      });\n\n      it('no string prop with null value', () => {\n        function MyComponent() {\n          return <div width={null} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('no string prop with function value', () => {\n        let fun = function() {};\n\n        function MyComponent() {\n          return <div width={fun} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('no string prop with symbol value', () => {\n        function MyComponent() {\n          return <div width={Symbol('foo')} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n    });\n\n    describe('boolean properties', function() {\n      it('boolean prop with true value', () => {\n        function MyComponent() {\n          return <div hidden={true} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div hidden></div>');\n      });\n\n      it('boolean prop with false value', () => {\n        function MyComponent() {\n          return <div hidden={false} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('boolean prop with self value', () => {\n        function MyComponent() {\n          return <div hidden=\"hidden\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div hidden></div>');\n      });\n\n      it('boolean prop with \"\" value', () => {\n        function MyComponent() {\n          return <div hidden=\"\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('boolean prop with string value', () => {\n        function MyComponent() {\n          return <div hidden=\"foo\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div hidden></div>');\n      });\n\n      it('boolean prop with array value', () => {\n        function MyComponent() {\n          return <div hidden={['foo', 'bar']} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div hidden></div>');\n      });\n\n      it('boolean prop with object value', () => {\n        function MyComponent() {\n          return <div hidden={{foo: 'bar'}} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div hidden></div>');\n      });\n\n      it('boolean prop with non-zero number value', () => {\n        function MyComponent() {\n          return <div hidden={10} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div hidden></div>');\n      });\n\n      it('boolean prop with zero value', () => {\n        function MyComponent() {\n          return <div hidden={0} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('no boolean prop with null value', () => {\n        function MyComponent() {\n          return <div hidden={null} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('no boolean prop with function value', () => {\n        let fun = function() {};\n        function MyComponent() {\n          return <div hidden={fun} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('no boolean prop with symbol value', () => {\n        function MyComponent() {\n          return <div hidden={Symbol('foo')} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n    });\n\n    describe('download property (combined boolean/string attribute)', function() {\n      it('download prop with true value', () => {\n        function MyComponent() {\n          return <a download={true} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a download></a>');\n      });\n\n      it('download prop with false value', () => {\n        function MyComponent() {\n          return <a download={false} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a></a>');\n      });\n\n      it('download prop with string value', () => {\n        function MyComponent() {\n          return <a download=\"myfile\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a download=\"myfile\"></a>');\n      });\n\n      it('download prop with string \"false\" value', () => {\n        function MyComponent() {\n          return <a download=\"false\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a download=\"false\"></a>');\n      });\n\n      it('download prop with string \"true\" value', () => {\n        function MyComponent() {\n          return <a download=\"true\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a download=\"true\"></a>');\n      });\n\n      it('download prop with number 0 value', () => {\n        function MyComponent() {\n          return <a download={0} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a download=\"0\"></a>');\n      });\n\n      it('no download prop with null value', () => {\n        function MyComponent() {\n          return <a download={null} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a></a>');\n      });\n\n      it('no download prop with undefined value', () => {\n        function MyComponent() {\n          return <a download={undefined} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a></a>');\n      });\n\n      it('no download prop with function value', () => {\n        let fun = function() {};\n        function MyComponent() {\n          return <a download={fun} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a></a>');\n      });\n\n      it('no download prop with symbol value', () => {\n        function MyComponent() {\n          return <a download={Symbol('foo')} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<a></a>');\n      });\n    });\n\n    describe('className property', function() {\n      it('className prop with string value', () => {\n        function MyComponent() {\n          return <div className=\"myClassName\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div class=\"myClassName\"></div>');\n      });\n\n      it('className prop with empty string value', () => {\n        function MyComponent() {\n          return <div className=\"\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div class=\"\"></div>');\n      });\n\n      it('no className prop with true value', () => {\n        function MyComponent() {\n          return <div className={true} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('no className prop with false value', () => {\n        function MyComponent() {\n          return <div className={false} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('no className prop with null value', () => {\n        function MyComponent() {\n          return <div className={null} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('badly cased className with a warning', () => {\n        function MyComponent() {\n          return <div classname=\"test\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div classname=\"test\"></div>');\n      });\n\n      it('className prop when given the alias with a warning', () => {\n        function MyComponent() {\n          return <div class=\"test\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div class=\"test\"></div>');\n      });\n    });\n\n    describe('htmlFor property', function() {\n      // TODO\n    });\n\n    describe('numeric properties', function() {\n      it('positive numeric property with positive value', () => {\n        function MyComponent() {\n          return <input size={2} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<input size=\"2\">');\n      });\n\n      it('numeric property with zero value', () => {\n        function MyComponent() {\n          return <ol start={0} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<ol start=\"0\"></ol>');\n      });\n\n      it('no positive numeric property with zero value', () => {\n        function MyComponent() {\n          return <input size={0} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<input>');\n      });\n\n      it('no numeric prop with function value', () => {\n        let fun = function() {};\n        function MyComponent() {\n          return <ol start={fun} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<ol></ol>');\n      });\n\n      it('no numeric prop with symbol value', () => {\n        function MyComponent() {\n          return <ol start={Symbol('foo')} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<ol></ol>');\n      });\n\n      it('no positive numeric prop with function value', () => {\n        let fun = function() {};\n        function MyComponent() {\n          return <input size={fun} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<input>');\n      });\n\n      it('no positive numeric prop with symbol value', () => {\n        let fun = function() {};\n        function MyComponent() {\n          return <input size={Symbol('foo')} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<input>');\n      });\n    });\n\n    describe('props with special meaning', function() {\n      it('no ref attribute', () => {\n        function MyComponent() {\n          return <div ref=\"foo\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('no children attribute', () => {\n        function MyComponent() {\n          return createElement('div', {}, 'foo');\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div>foo</div>');\n      });\n\n      it('no key attribute', () => {\n        function MyComponent() {\n          return <div key=\"foo\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('no dangerouslySetInnerHTML attribute', () => {\n        function MyComponent() {\n          return <div dangerouslySetInnerHTML={{__html: '<foo />'}} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div><foo /></div>');\n      });\n    });\n\n    describe('inline styles', function() {\n      // TODO\n    });\n\n    describe('aria attributes', function() {\n      it('simple strings', () => {\n        function MyComponent() {\n          return <div aria-label=\"hello\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div aria-label=\"hello\"></div>');\n      });\n\n      it('aria string prop with false value', () => {\n        function MyComponent() {\n          return <div aria-label={false} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div aria-label=\"false\"></div>');\n      });\n\n      it('aria string prop with null value', () => {\n        function MyComponent() {\n          return <div aria-label={null} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('\"aria\" attribute with a warning', () => {\n        function MyComponent() {\n          return <div aria=\"hello\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div aria=\"hello\"></div>');\n      });\n    });\n\n    describe('cased attributes', function() {\n      it('badly cased aliased HTML attribute with a warning', () => {\n        function MyComponent() {\n          return <meta httpequiv=\"refresh\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<meta httpequiv=\"refresh\">');\n      });\n\n      it('badly cased SVG attribute with a warning', () => {\n        function MyComponent() {\n          return <svg>\n            <text textlength=\"10\" />\n          </svg>;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<svg><text textlength=\"10\"></text></svg>');\n      });\n\n      it('no badly cased aliased SVG attribute alias', () => {\n        function MyComponent() {\n          return <svg>\n            <text strokedasharray=\"10 10\" />\n          </svg>;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<svg><text strokedasharray=\"10 10\"></text></svg>');\n      });\n\n      it('no badly cased original SVG attribute that is aliased', () => {\n        function MyComponent() {\n          return <svg>\n            <text stroke-dasharray=\"10 10\" />\n          </svg>;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<svg><text stroke-dasharray=\"10 10\"></text></svg>');\n      });\n    });\n\n    describe('unknown attributes', function() {\n      it('unknown attributes', () => {\n        function MyComponent() {\n          return <div foo=\"bar\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div foo=\"bar\"></div>');\n      });\n\n      it('unknown data- attributes', () => {\n        function MyComponent() {\n          return <div data-foo=\"bar\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div data-foo=\"bar\"></div>');\n      });\n\n      it('badly cased reserved attributes', () => {\n        function MyComponent() {\n          return <div CHILDREN=\"5\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div CHILDREN=\"5\"></div>');\n      });\n\n      it('\"data\" attribute', () => {\n        function MyComponent() {\n          return <object data=\"hello\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<object data=\"hello\"></object>');\n      });\n\n      it('no unknown data- attributes with null value', () => {\n        function MyComponent() {\n          return <div data-foo={null} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('unknown data- attributes with casing', () => {\n        function MyComponent() {\n          return <div data-fooBar=\"true\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div data-fooBar=\"true\"></div>');\n      });\n\n      it('unknown data- attributes with boolean true', () => {\n        function MyComponent() {\n          return <div data-foobar={true} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div data-foobar=\"true\"></div>');\n      });\n\n      it('unknown data- attributes with boolean false', () => {\n        function MyComponent() {\n          return <div data-foobar={false} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div data-foobar=\"false\"></div>');\n      });\n\n      it('no unknown data- attributes with casing and null value', () => {\n        function MyComponent() {\n          return <div data-foobar={null} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('custom attributes for non-standard elements', () => {\n        function MyComponent() {\n          return <nonstandard foo=\"bar\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<nonstandard foo=\"bar\"></nonstandard>');\n      });\n\n      it('SVG tags with dashes in them', () => {\n        function MyComponent() {\n          return <svg>\n            <font-face accent-height={10} />\n          </svg>;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<svg><font-face accent-height=\"10\"></font-face></svg>');\n      });\n\n      it('cased custom attributes', () => {\n        function MyComponent() {\n          return <div fooBar=\"test\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div fooBar=\"test\"></div>');\n      });\n    });\n\n    describe('event attributes', function() {\n      it('no HTML events', () => {\n        function MyComponent() {\n          return <div onClick={() => {}} />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div></div>');\n      });\n\n      it('unknown events', () => {\n        function MyComponent() {\n          return <div onunknownevent=\"alert(&quot;hack&quot;)\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div onunknownevent=\\\"alert(&quot;hack&quot;)\\\"></div>');\n      });\n\n      it('custom attribute named `on`', () => {\n        function MyComponent() {\n          return <div on=\"tap:do-something\" />;\n        }\n\n        const str = renderToString(<MyComponent />);\n        expect(str).toBe('<div on=\"tap:do-something\"></div>');\n      });\n    });\n  });\n\n  describe('custom elements', () => {\n    it('class for custom elements', () => {\n      function MyComponent() {\n        return <div is=\"custom-element\" class=\"test\" />;\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<div is=\"custom-element\" class=\"test\"></div>');\n    });\n\n    it('className for custom elements', () => {\n      function MyComponent() {\n        return <div is=\"custom-element\" className=\"test\" />;\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<div is=\"custom-element\" class=\"test\"></div>');\n    });\n\n    it('htmlFor attribute for custom elements', () => {\n      function MyComponent() {\n        return <div is=\"custom-element\" htmlFor=\"test\" />;\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<div is=\"custom-element\" htmlFor=\"test\"></div>');\n    });\n\n    it('for attribute for custom elements', () => {\n      function MyComponent() {\n        return <div is=\"custom-element\" for=\"test\" />;\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<div is=\"custom-element\" for=\"test\"></div>');\n    });\n\n    it('unknown attributes for custom elements', () => {\n      function MyComponent() {\n        return <custom-element foo=\"bar\" />;\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<custom-element foo=\"bar\"></custom-element>');\n    });\n\n    it('unknown `on*` attributes for custom elements', () => {\n      function MyComponent() {\n        return <custom-element onunknown=\"bar\" />;\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<custom-element onunknown=\"bar\"></custom-element>');\n    });\n\n    it('no unknown boolean `true` attributes', () => {\n      function MyComponent() {\n        return <custom-element foo={true} />;\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<custom-element></custom-element>');\n    });\n\n    it('no unknown boolean `false` attributes', () => {\n      function MyComponent() {\n        return <custom-element foo={false} />;\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<custom-element></custom-element>');\n    });\n\n    it('no unknown attributes for custom elements with null value', () => {\n      function MyComponent() {\n        return <custom-element foo={null} />;\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<custom-element></custom-element>');\n    });\n\n    it('unknown attributes for custom elements using is', () => {\n      function MyComponent() {\n        return <div is=\"custom-element\" foo=\"bar\" />;\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<div is=\"custom-element\" foo=\"bar\"></div>');\n    });\n\n    it('no unknown attributes for custom elements using is with null value', () => {\n      function MyComponent() {\n        return <div is=\"custom-element\" foo={null} />;\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<div is=\"custom-element\"></div>');\n    });\n  });\n});"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/basic.js",
    "content": "/* @jsx createElement */\n\nimport {createElement} from 'rax';\nimport {renderToString} from '../index';\n\ndescribe('renderToString', () => {\n  describe('basic rendering', function() {\n    it('render a blank div', () => {\n      function MyComponent() {\n        return <div />;\n      }\n\n      let str = renderToString(<MyComponent />);\n      expect(str).toBe('<div></div>');\n    });\n\n    it('render a self-closing tag', () => {\n      function MyComponent() {\n        return <br />;\n      }\n\n      let str = renderToString(<MyComponent />);\n      expect(str).toBe('<br>');\n    });\n\n    it('render a self-closing tag as a child', () => {\n      function MyComponent() {\n        return (\n          <div>\n            <br />\n          </div>\n        );\n      }\n\n      let str = renderToString(<MyComponent />);\n      expect(str).toBe('<div><br></div>');\n    });\n\n    it('render a string', () => {\n      function MyComponent() {\n        return 'Hello';\n      }\n\n      let str = renderToString(<MyComponent />);\n      expect(str).toBe('Hello');\n    });\n\n    it('render a number', () => {\n      function MyComponent() {\n        return 42;\n      }\n\n      let str = renderToString(<MyComponent />);\n      expect(str).toBe('42');\n    });\n\n    it('render child with zero value', () => {\n      const value = 0;\n\n      function MyComponent() {\n        return <span>{value}</span>;\n      }\n\n      let str = renderToString(<MyComponent />);\n      expect(str).toBe('<span>0</span>');\n    });\n\n    it('render an array with one child', () => {\n      function MyComponent() {\n        return [<div key={1}>text1</div>];\n      }\n\n      let str = renderToString(<MyComponent />);\n      expect(str).toBe('<div>text1</div>');\n    });\n\n    it('render an array with several children', () => {\n      let Header = props => {\n        return <p>header</p>;\n      };\n      let Footer = props => {\n        return [<h2 key={1}>footer</h2>, <h3 key={2}>about</h3>];\n      };\n\n      function MyComponent() {\n        return [\n          <div key={1}>text1</div>,\n          <span key={2}>text2</span>,\n          <Header key={3} />,\n          <Footer key={4} />,\n        ];\n      }\n\n      let str = renderToString(<MyComponent />);\n      expect(str).toBe('<div>text1</div><span>text2</span><p>header</p><h2>footer</h2><h3>about</h3>');\n    });\n\n    it('render a nested array', () => {\n      function MyComponent() {\n        return [\n          [<div key={1}>text1</div>],\n          <span key={1}>text2</span>,\n          [[[null, <p key={1} />], false]],\n        ];\n      }\n\n      let str = renderToString(<MyComponent />);\n      expect(str).toBe('<div>text1</div><span>text2</span><!-- _ --><p></p><!-- _ -->');\n    });\n\n    // TODO: render an iterable\n    it('render an iterable', async() => {\n    });\n\n    it('render emptyish value', () => {\n      expect(renderToString(0)).toBe('0');\n      expect(renderToString(<div>{''}</div>)).toBe('<div></div>');\n      expect(renderToString([])).toBe('');\n      expect(renderToString(false)).toBe('<!-- _ -->');\n      expect(renderToString(true)).toBe('<!-- _ -->');\n      expect(renderToString(undefined)).toBe('<!-- _ -->');\n      expect(renderToString([[[false]], undefined])).toBe('<!-- _ --><!-- _ -->');\n    });\n  });\n});"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/context.js",
    "content": "/* @jsx createElement */\n\nimport {createElement, createContext, Component, Fragment, useContext} from 'rax';\nimport PropTypes from 'prop-types';\nimport {renderToString} from '../index';\n\ndescribe('context', () => {\n  describe('basic context', function() {\n    let Context, PurpleContextProvider, RedContextProvider, Consumer;\n    beforeEach(() => {\n      Context = createContext('none');\n\n      class Parent extends Component {\n        render() {\n          return (\n            <Context.Provider value={this.props.text}>\n              {this.props.children}\n            </Context.Provider>\n          );\n        }\n      }\n      Consumer = Context.Consumer;\n      PurpleContextProvider = props => (\n        <Parent text=\"purple\">{props.children}</Parent>\n      );\n      RedContextProvider = props => (\n        <Parent text=\"red\">{props.children}</Parent>\n      );\n    });\n\n    it('class child with context', () => {\n      class ClassChildWithContext extends Component {\n        render() {\n          return (\n            <div>\n              <Consumer>{text => text}</Consumer>\n            </div>\n          );\n        }\n      }\n\n      const str = renderToString(\n        <PurpleContextProvider>\n          <ClassChildWithContext />\n        </PurpleContextProvider>\n      );\n\n      expect(str).toBe('<div>purple</div>');\n    });\n\n    it('stateless child with context', () => {\n      function FunctionChildWithContext(props) {\n        return <Consumer>{text => text}</Consumer>;\n      }\n\n      const str = renderToString(\n        <PurpleContextProvider>\n          <FunctionChildWithContext />\n        </PurpleContextProvider>\n      );\n\n      expect(str).toBe('purple');\n    });\n\n    it('class child with default context', () => {\n      class ClassChildWithWrongContext extends Component {\n        render() {\n          return (\n            <div>\n              <Consumer>{text => text}</Consumer>\n            </div>\n          );\n        }\n      }\n\n      const str = renderToString(<ClassChildWithWrongContext />);\n\n      expect(str).toBe('<div>none</div>');\n    });\n\n    it('stateless child with wrong context', () => {\n      function FunctionChildWithWrongContext(props) {\n        return <Consumer>{text => text}</Consumer>;\n      }\n\n      const str = renderToString(<FunctionChildWithWrongContext />);\n\n      expect(str).toBe('none');\n    });\n\n    it('with context passed through to a grandchild', () => {\n      function Grandchild(props) {\n        return (\n          <div>\n            <Consumer>{text => text}</Consumer>\n          </div>\n        );\n      }\n\n      const Child = props => <Grandchild />;\n\n      const str = renderToString(\n        <PurpleContextProvider>\n          <Child />\n        </PurpleContextProvider>\n      );\n\n      expect(str).toBe('<div>purple</div>');\n    });\n\n    it('a child context overriding a parent context', () => {\n      function Grandchild(props) {\n        return (\n          <div>\n            <Consumer>{text => text}</Consumer>\n          </div>\n        );\n      }\n\n      const str = renderToString(\n        <PurpleContextProvider>\n          <RedContextProvider>\n            <Grandchild />\n          </RedContextProvider>\n        </PurpleContextProvider>\n      );\n\n      expect(str).toBe('<div>red</div>');\n    });\n\n    it('multiple contexts', () => {\n      const Theme = createContext('dark');\n      const Language = createContext('french');\n      class Parent extends Component {\n        render() {\n          return (\n            <Theme.Provider value=\"light\">\n              <Child />\n            </Theme.Provider>\n          );\n        }\n      }\n\n      function Child() {\n        return (\n          <Language.Provider value=\"english\">\n            <Grandchild />\n          </Language.Provider>\n        );\n      }\n\n      const Grandchild = props => {\n        return (\n          <div>\n            <Theme.Consumer>\n              {theme => <div id=\"theme\">{theme}</div>}\n            </Theme.Consumer>\n            <Language.Consumer>\n              {language => <div id=\"language\">{language}</div>}\n            </Language.Consumer>\n          </div>\n        );\n      };\n\n      const str = renderToString(<Parent />);\n\n      expect(str).toBe('<div><div id=\"theme\">light</div><div id=\"language\">english</div></div>');\n    });\n\n    it('nested context unwinding', () => {\n      const Theme = createContext('dark');\n      const Language = createContext('french');\n\n      const App = () => (\n        <div>\n          <Theme.Provider value=\"light\">\n            <Language.Provider value=\"english\">\n              <Theme.Provider value=\"dark\">\n                <Theme.Consumer>\n                  {theme => <div id=\"theme1\">{theme}</div>}\n                </Theme.Consumer>\n              </Theme.Provider>\n              <Theme.Consumer>\n                {theme => <div id=\"theme2\">{theme}</div>}\n              </Theme.Consumer>\n              <Language.Provider value=\"sanskrit\">\n                <Theme.Provider value=\"blue\">\n                  <Theme.Provider value=\"red\">\n                    <Language.Consumer>\n                      {() => (\n                        <Language.Provider value=\"chinese\">\n                          <Language.Provider value=\"hungarian\" />\n                          <Language.Consumer>\n                            {language => <div id=\"language1\">{language}</div>}\n                          </Language.Consumer>\n                        </Language.Provider>\n                      )}\n                    </Language.Consumer>\n                  </Theme.Provider>\n                  <Language.Consumer>\n                    {language => (\n                      <Fragment>\n                        <Theme.Consumer>\n                          {theme => <div id=\"theme3\">{theme}</div>}\n                        </Theme.Consumer>\n                        <div id=\"language2\">{language}</div>\n                      </Fragment>\n                    )}\n                  </Language.Consumer>\n                </Theme.Provider>\n              </Language.Provider>\n            </Language.Provider>\n          </Theme.Provider>\n          <Language.Consumer>\n            {language => <div id=\"language3\">{language}</div>}\n          </Language.Consumer>\n        </div>\n      );\n\n      const str = renderToString(<App />);\n\n      expect(str).toBe('<div><div id=\"theme1\">dark</div><div id=\"theme2\">light</div><!-- _ --><div id=\"language1\">chinese</div><div id=\"theme3\">blue</div><div id=\"language2\">sanskrit</div><div id=\"language3\">french</div></div>');\n    });\n\n    it('function context', () => {\n      let Ctx = createContext();\n\n      function Provider() {\n        return (\n          <Ctx.Provider value={this.props.value}>\n            {this.props.children}\n          </Ctx.Provider>\n        );\n      }\n\n      function FnConsumer() {\n        return useContext(Ctx);\n      }\n\n      const str = renderToString(\n        <Provider value=\"a\">\n          <span>\n            <FnConsumer />\n          </span>\n        </Provider>\n      );\n\n      expect(str).toBe('<span>a</span>');\n    });\n  });\n\n  // contextTypes & childContextTypes is not work in ssr\n  describe('legacy context', function() {\n    let Warning = 'Warning: The legacy \"contextTypes\" and \"childContextTypes\" API not working properly in server renderer, use the new context API. ';\n\n    let PurpleContext;\n    beforeEach(() => {\n      class Parent extends Component {\n        getChildContext() {\n          return {text: this.props.text};\n        }\n        render() {\n          return this.props.children;\n        }\n      }\n\n      PurpleContext = props => <Parent text=\"purple\">{props.children}</Parent>;\n    });\n\n    it('class child with contextTypes', () => {\n      expect(() => {\n        class ClassChildWithContext extends Component {\n          render() {\n            return <div>{this.context.text}</div>;\n          }\n        }\n        ClassChildWithContext.contextTypes = {text: PropTypes.string};\n\n        const str = renderToString(\n          <PurpleContext>\n            <ClassChildWithContext />\n          </PurpleContext>\n        );\n\n        expect(str).toBe('<div>purple</div>');\n      }).toWarnDev(Warning + '(Current: ClassChildWithContext)', {withoutStack: true});\n    });\n\n    it('stateless child with contextTypes', () => {\n      expect(() => {\n        function FunctionChildWithContext(props, context) {\n          return <div>{context.text}</div>;\n        }\n        FunctionChildWithContext.contextTypes = {text: PropTypes.string};\n\n        const str = renderToString(\n          <PurpleContext>\n            <FunctionChildWithContext />\n          </PurpleContext>\n        );\n\n        expect(str).toBe('<div>purple</div>');\n      }).toWarnDev(Warning + '(Current: FunctionChildWithContext)', {withoutStack: true});\n    });\n\n    it('parent with childContextTypes', () => {\n      expect(() => {\n        class Parent extends Component {\n          getChildContext() {\n            return {text: this.props.text};\n          }\n          render() {\n            return this.props.children;\n          }\n        }\n\n        Parent.childContextTypes = {text: PropTypes.string};\n\n        const PurpleContext = props => <Parent text=\"purple\">{props.children}</Parent>;\n\n        function FunctionChildWithContext(props, context) {\n          return <div>{context.text}</div>;\n        }\n\n        const str = renderToString(\n          <PurpleContext>\n            <FunctionChildWithContext />\n          </PurpleContext>\n        );\n\n        expect(str).toBe('<div>purple</div>');\n      }).toWarnDev(Warning + '(Current: Parent)', {withoutStack: true});\n    });\n\n    it('can not filter context with contextTypes on the server', () => {\n      expect(() => {\n        function FunctionChildWithContext(props, context) {\n          return <div>{context.text}</div>;\n        }\n        FunctionChildWithContext.contextTypes = {value: PropTypes.string};\n\n        const str = renderToString(\n          <PurpleContext>\n            <FunctionChildWithContext />\n          </PurpleContext>\n        );\n\n        expect(str).not.toBe('<div><!-- _ --></div>');\n      }).toWarnDev(Warning + '(Current: FunctionChildWithContext)', {withoutStack: true});\n    });\n\n    it('can not prevent context be passed to child without contextTypes on the server', () => {\n      function FunctionChildWithContext(props, context) {\n        return <div>{context.text}</div>;\n      }\n\n      const str = renderToString(\n        <PurpleContext>\n          <FunctionChildWithContext />\n        </PurpleContext>\n      );\n\n      expect(str).not.toBe('<div><!-- _ --></div>');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/elements.js",
    "content": "/* @jsx createElement */\n\nimport {createElement, Component} from 'rax';\nimport {renderToString} from '../index';\n\ndescribe('elements and children', () => {\n  describe('text children', function() {\n    it('a div with text', () => {\n      const str = renderToString(\n        <div>Text</div>\n      );\n      expect(str).toBe('<div>Text</div>');\n    });\n\n    it('a div with text with flanking whitespace', () => {\n      const str = renderToString(\n        <div>  Text </div>\n      );\n      expect(str).toBe('<div>  Text </div>');\n    });\n\n    it('a div with an empty text child', () => {\n      const str = renderToString(\n        <div>{''}</div>\n      );\n      expect(str).toBe('<div></div>');\n    });\n\n    it('a div with multiple empty text children', () => {\n      const str = renderToString(\n        <div>\n          {''}\n          {''}\n          {''}\n        </div>\n      );\n      expect(str).toBe('<div><!--|--><!--|--></div>');\n    });\n\n    it('a div with multiple whitespace children', () => {\n      const str = renderToString(\n        <div>\n          {' '}\n          {' '}\n          {' '}\n        </div>\n      );\n      expect(str).toBe('<div> <!--|--> <!--|--> </div>');\n    });\n\n    it('a div with text sibling to a node', () => {\n      const str = renderToString(\n        <div>\n          Text<span>More Text</span>\n        </div>\n      );\n      expect(str).toBe('<div>Text<span>More Text</span></div>');\n    });\n\n    it('a non-standard element with text', () => {\n      const str = renderToString(\n        <nonstandard>\n          Text\n        </nonstandard>\n      );\n      expect(str).toBe('<nonstandard>Text</nonstandard>');\n    });\n\n    it('a custom element with text', () => {\n      const str = renderToString(\n        <custom-element>\n          Text\n        </custom-element>\n      );\n      expect(str).toBe('<custom-element>Text</custom-element>');\n    });\n\n    it('a leading blank child with a text sibling', () => {\n      const str = renderToString(<div>{''}foo</div>);\n      expect(str).toBe('<div><!--|-->foo</div>');\n    });\n\n    it('a trailing blank child with a text sibling', () => {\n      const str = renderToString(<div>foo{''}</div>);\n      expect(str).toBe('<div>foo<!--|--></div>');\n    });\n\n    it('an element with two text children', () => {\n      const str = renderToString(\n        <div>\n          {'foo'}\n          {'bar'}\n        </div>\n      );\n      expect(str).toBe('<div>foo<!--|-->bar</div>');\n    });\n\n    it('a component returning text node between two text nodes', () => {\n      const B = () => 'b';\n      const str = renderToString(\n        <div>\n          {'a'}\n          <B />\n          {'c'}\n        </div>\n      );\n      expect(str).toBe('<div>a<!--|-->b<!--|-->c</div>');\n    });\n\n    it('a tree with sibling host and text nodes', () => {\n      class X extends Component {\n        render() {\n          return [null, [<Y key=\"1\" />], false];\n        }\n      }\n\n      function Y() {\n        return [<Z key=\"1\" />, ['c']];\n      }\n\n      function Z() {\n        return null;\n      }\n\n      const str = renderToString(\n        <div>\n          {[['a'], 'b']}\n          <div>\n            <X key=\"1\" />\n            d\n          </div>\n          e\n        </div>,\n      );\n      expect(str).toBe('<div>a<!--|-->b<div><!-- _ --><!-- _ -->c<!-- _ -->d</div>e</div>');\n    });\n  });\n\n  describe('number children', function() {\n    it('a number as single child', () => {\n      const str = renderToString(\n        <div>{3}</div>\n      );\n      expect(str).toBe('<div>3</div>');\n    });\n\n    it('zero as single child', () => {\n      const str = renderToString(\n        <div>{0}</div>\n      );\n      expect(str).toBe('<div>0</div>');\n    });\n\n    it('an element with number and text children', () => {\n      const str = renderToString(\n        <div>\n          {'foo'}\n          {40}\n        </div>\n      );\n      expect(str).toBe('<div>foo<!--|-->40</div>');\n    });\n  });\n\n  describe('null, false, and undefined children', function() {\n    it('render null single child as blank', () => {\n      const str = renderToString(\n        <div>{null}</div>\n      );\n      expect(str).toBe('<div><!-- _ --></div>');\n    });\n\n    it('render false single child as blank', () => {\n      const str = renderToString(\n        <div>{false}</div>\n      );\n      expect(str).toBe('<div><!-- _ --></div>');\n    });\n\n    it('render undefined single child as blank', () => {\n      const str = renderToString(\n        <div>{undefined}</div>\n      );\n      expect(str).toBe('<div><!-- _ --></div>');\n    });\n\n    it('render a null component children as empty', () => {\n      const NullComponent = () => null;\n      const str = renderToString(\n        <div><NullComponent /></div>\n      );\n      expect(str).toBe('<div><!-- _ --></div>');\n    });\n\n    it('render null children as blank', () => {\n      const str = renderToString(\n        <div>{null}foo</div>\n      );\n      expect(str).toBe('<div><!-- _ -->foo</div>');\n    });\n\n    it('render false children as blank', () => {\n      const str = renderToString(\n        <div>{false}foo</div>\n      );\n      expect(str).toBe('<div><!-- _ -->foo</div>');\n    });\n\n    it('render null and false children together as blank', () => {\n      const str = renderToString(\n        <div>\n          {false}\n          {null}foo{null}\n          {false}\n        </div>\n      );\n      expect(str).toBe('<div><!-- _ --><!-- _ -->foo<!-- _ --><!-- _ --></div>');\n    });\n\n    it('render only null and false children as blank', () => {\n      const str = renderToString(\n        <div>\n          {false}\n          {null}\n          {null}\n          {false}\n        </div>\n      );\n      expect(str).toBe('<div><!-- _ --><!-- _ --><!-- _ --><!-- _ --></div>');\n    });\n  });\n\n  describe('elements with implicit namespaces', function() {\n    it('an svg element', () => {\n      const str = renderToString(\n        <svg />\n      );\n      expect(str).toBe('<svg></svg>');\n    });\n\n    it('svg child element with an attribute', () => {\n      const str = renderToString(\n        <svg viewBox=\"0 0 0 0\" />\n      );\n      expect(str).toBe('<svg viewBox=\"0 0 0 0\"></svg>');\n    });\n\n    it('svg child element with a namespace attribute', () => {\n      const str = renderToString(\n        <svg>\n          <image xlinkHref=\"http://i.imgur.com/w7GCRPb.png\" />\n        </svg>\n      );\n      expect(str).toBe('<svg><image xlinkHref=\"http://i.imgur.com/w7GCRPb.png\"></image></svg>');\n    });\n\n    it('svg child element with a badly cased alias', () => {\n      const str = renderToString(\n        <svg>\n          <image xlinkhref=\"http://i.imgur.com/w7GCRPb.png\" />\n        </svg>\n      );\n      expect(str).toBe('<svg><image xlinkhref=\"http://i.imgur.com/w7GCRPb.png\"></image></svg>');\n    });\n\n    it('svg element with a tabIndex attribute', () => {\n      const str = renderToString(<svg tabIndex=\"1\" />);\n      expect(str).toBe('<svg tabIndex=\"1\"></svg>');\n    });\n\n    it('svg element with a badly cased tabIndex attribute', () => {\n      const str = renderToString(<svg tabindex=\"1\" />);\n      expect(str).toBe('<svg tabindex=\"1\"></svg>');\n    });\n\n    it('svg element with a mixed case name', () => {\n      const str = renderToString(\n        <svg>\n          <filter>\n            <feMorphology />\n          </filter>\n        </svg>\n      );\n      expect(str).toBe('<svg><filter><feMorphology></feMorphology></filter></svg>');\n    });\n\n    it('a math element', () => {\n      const str = renderToString(<math />);\n      expect(str).toBe('<math></math>');\n    });\n  });\n\n  it('an img', () => {\n    const str = renderToString(<img />);\n    expect(str).toBe('<img>');\n  });\n\n  it('a button', () => {\n    const str = renderToString(<button />);\n    expect(str).toBe('<button></button>');\n  });\n\n  it('a noscript with children', () => {\n    const str = renderToString(\n      <noscript>\n        <div>Enable JavaScript to run this app.</div>\n      </noscript>\n    );\n    expect(str).toBe('<noscript><div>Enable JavaScript to run this app.</div></noscript>');\n  });\n\n  describe('elements with implicit namespaces', function() {\n    it('a div with dangerouslySetInnerHTML number', () => {\n      const str = renderToString(\n        <div>\n          <span dangerouslySetInnerHTML={{__html: 0}} />\n        </div>\n      );\n      expect(str).toBe('<div><span>0</span></div>');\n    });\n\n    it('a div with dangerouslySetInnerHTML boolean', () => {\n      const str = renderToString(\n        <div>\n          <span dangerouslySetInnerHTML={{__html: false}} />\n        </div>\n      );\n      expect(str).toBe('<div><span>false</span></div>');\n    });\n\n    it('a div with dangerouslySetInnerHTML text string', () => {\n      const str = renderToString(\n        <div>\n          <span dangerouslySetInnerHTML={{__html: 'hello'}} />\n        </div>\n      );\n      expect(str).toBe('<div><span>hello</span></div>');\n    });\n\n    it('a div with dangerouslySetInnerHTML element string', () => {\n      const str = renderToString(\n        <div dangerouslySetInnerHTML={{__html: \"<span id='child'/>\"}} />\n      );\n      expect(str).toBe(\"<div><span id='child'/></div>\");\n    });\n\n    it('a div with dangerouslySetInnerHTML object', () => {\n      const obj = {\n        toString() {\n          return \"<span id='child'/>\";\n        },\n      };\n      const str = renderToString(\n        <div dangerouslySetInnerHTML={{__html: obj}} />\n      );\n      expect(str).toBe(\"<div><span id='child'/></div>\");\n    });\n\n    it('a div with dangerouslySetInnerHTML set to null', () => {\n      const str = renderToString(\n        <div dangerouslySetInnerHTML={{__html: null}} />\n      );\n      expect(str).toBe('<div></div>');\n    });\n\n    it('a div with dangerouslySetInnerHTML set to undefined', () => {\n      const str = renderToString(\n        <div dangerouslySetInnerHTML={{__html: undefined}} />\n      );\n      expect(str).toBe('<div></div>');\n    });\n  });\n\n  describe('newline-eating elements', function() {\n    it('a newline-eating tag with content not starting with \\\\n', () => {\n      const str = renderToString(\n        <pre>Hello</pre>\n      );\n      expect(str).toBe('<pre>Hello</pre>');\n    });\n\n    it('a newline-eating tag with content starting with \\\\n', () => {\n      const str = renderToString(\n        <pre>{'\\nHello'}</pre>\n      );\n      expect(str).toBe('<pre>\\nHello</pre>');\n    });\n\n    it('a normal tag with content starting with \\\\n', () => {\n      const str = renderToString(\n        <div>{'\\nHello'}</div>\n      );\n      expect(str).toBe('<div>\\nHello</div>');\n    });\n  });\n\n  describe('different component implementations', function() {\n    it('stateless components', () => {\n      const FunctionComponent = () => <div>foo</div>;\n      const str = renderToString(<FunctionComponent />);\n      expect(str).toBe('<div>foo</div>');\n    });\n\n    it('ES6 class components', () => {\n      class ClassComponent extends Component {\n        render() {\n          return <div>foo</div>;\n        }\n      }\n      const str = renderToString(<ClassComponent />);\n      expect(str).toBe('<div>foo</div>');\n    });\n\n    it('throw when rendering factory components', () => {\n      const FactoryComponent = () => {\n        return {\n          render: function() {\n            return <div>foo</div>;\n          },\n        };\n      };\n      expect(() => {\n        renderToString(<FactoryComponent />);\n      }).toWarnDev('Invalid element type, expected types: Element instance, string, boolean, array, null, undefined. (found: object with keys {render})', {withoutStack: true});\n    });\n  });\n\n  describe('component hierarchies', function() {\n    it('single child hierarchies of components', () => {\n      const Component = props => <div>{props.children}</div>;\n      const str = renderToString(\n        <Component>\n          <Component>\n            <Component>\n              <Component />\n            </Component>\n          </Component>\n        </Component>\n      );\n      expect(str).toBe('<div><div><div><div><!-- _ --></div></div></div></div>');\n    });\n\n    it('multi-child hierarchies of components', () => {\n      const Component = props => <div>{props.children}</div>;\n      const str = renderToString(\n        <Component>\n          <Component>\n            <Component />\n            <Component />\n          </Component>\n          <Component>\n            <Component />\n            <Component />\n          </Component>\n        </Component>\n      );\n      expect(str).toBe('<div><div><div><!-- _ --></div><div><!-- _ --></div></div><div><div><!-- _ --></div><div><!-- _ --></div></div></div>');\n    });\n\n    it('a div with a child', () => {\n      const str = renderToString(\n        <div id=\"parent\">\n          <div id=\"child\" />\n        </div>\n      );\n      expect(str).toBe('<div id=\"parent\"><div id=\"child\"></div></div>');\n    });\n\n    it('a div with multiple children', () => {\n      const str = renderToString(\n        <div id=\"parent\">\n          <div id=\"child1\" />\n          <div id=\"child2\" />\n        </div>\n      );\n      expect(str).toBe('<div id=\"parent\"><div id=\"child1\"></div><div id=\"child2\"></div></div>');\n    });\n\n    it('a div with multiple children separated by whitespace', () => {\n      const str = renderToString(\n        <div id=\"parent\">\n          <div id=\"child1\" /> <div id=\"child2\" />\n        </div>\n      );\n      expect(str).toBe('<div id=\"parent\"><div id=\"child1\"></div> <div id=\"child2\"></div></div>');\n    });\n\n    it('a div with a single child surrounded by whitespace', () => {\n      const str = renderToString(\n        <div id=\"parent\">  <div id=\"child\" />   </div>\n      );\n      expect(str).toBe('<div id=\"parent\">  <div id=\"child\"></div>   </div>');\n    });\n\n    it('a composite with multiple children', () => {\n      const Component = props => props.children;\n      const str = renderToString(\n        <Component>{['a', 'b', [undefined], [[false, 'c']]]}</Component>,\n      );\n      expect(str).toBe('a<!--|-->b<!-- _ --><!-- _ -->c');\n    });\n  });\n\n  describe('escaping >, <, and &', function() {\n    it('>,<, and & as single child', () => {\n      const str = renderToString(\n        <div>{'<span>Text&quot;</span>'}</div>\n      );\n      expect(str).toBe('<div>&lt;span&gt;Text&amp;quot;&lt;/span&gt;</div>');\n    });\n\n    it('>,<, and & as multiple children', () => {\n      const str = renderToString(\n        <div>\n          {'<span>Text1&quot;</span>'}\n          {'<span>Text2&quot;</span>'}\n        </div>\n      );\n      expect(str).toBe('<div>&lt;span&gt;Text1&amp;quot;&lt;/span&gt;<!--|-->&lt;span&gt;Text2&amp;quot;&lt;/span&gt;</div>');\n    });\n  });\n\n  describe('carriage return and null character', function() {\n    it('an element with one text child with special characters', () => {\n      const str = renderToString(\n        <div>{'foo\\rbar\\r\\nbaz\\nqux\\u0000'}</div>\n      );\n      expect(str).toBe('<div>foo\\rbar\\r\\nbaz\\nqux\\u0000</div>');\n    });\n\n    it('an element with two text children with special characters', () => {\n      const str = renderToString(\n        <div>\n          {'foo\\rbar'}\n          {'\\r\\nbaz\\nqux\\u0000'}\n        </div>\n      );\n      expect(str).toBe('<div>foo\\rbar<!--|-->\\r\\nbaz\\nqux\\u0000</div>');\n    });\n\n    it('an element with an attribute value with special characters', () => {\n      const str = renderToString(\n        <a title={'foo\\rbar\\r\\nbaz\\nqux\\u0000'} />\n      );\n      expect(str).toBe('<a title=\"foo\\rbar\\r\\nbaz\\nqux\\u0000\"></a>');\n    });\n  });\n\n  describe('components that throw errors', function() {\n    it('render a function returning undefined', () => {\n      const UndefinedComponent = () => undefined;\n      const str = renderToString(\n        <UndefinedComponent />\n      );\n      expect(str).toBe('<!-- _ -->');\n    });\n\n    it('render a function returning undefined', () => {\n      class UndefinedComponent extends Component {\n        render() {\n          return undefined;\n        }\n      }\n      const str = renderToString(\n        <UndefinedComponent />\n      );\n      expect(str).toBe('<!-- _ -->');\n    });\n\n    it('throw error when rendering a function returning an object', () => {\n      const ObjectComponent = () => ({x: 123});\n      expect(() => {\n        renderToString(\n          <ObjectComponent />\n        );\n      }).toWarnDev('Invalid element type, expected types: Element instance, string, boolean, array, null, undefined. (found: object with keys {x})', {withoutStack: true});\n    });\n\n    it('throw error when rendering a class returning an object', () => {\n      class ObjectComponent extends Component {\n        render() {\n          return {x: 123};\n        }\n      }\n\n      expect(() => {\n        renderToString(\n          <ObjectComponent />\n        );\n      }).toWarnDev('Invalid element type, expected types: Element instance, string, boolean, array, null, undefined. (found: object with keys {x})', {withoutStack: true});\n    });\n\n    it('throw error when rendering top-level object', () => {\n      expect(() => {\n        renderToString({\n          x: 123\n        });\n      }).toWarnDev('Invalid element type, expected types: Element instance, string, boolean, array, null, undefined. (found: object with keys {x})', {withoutStack: true});\n    });\n  });\n\n  describe('badly-typed elements', function() {\n    it('render object', () => {\n      let EmptyComponent = {};\n      expect(() => {\n        renderToString(<EmptyComponent />);\n      }).toWarnDev('Invalid element type, expected types: Element instance, string, boolean, array, null, undefined. (found: object with keys {type,key,ref,props,_owner})', {withoutStack: true});\n    });\n\n    it('throw error when rendering null', () => {\n      let NullComponent = null;\n      expect(() => {\n        renderToString(<NullComponent />);\n      }).toThrowError('Invalid element type, expected a string or a class/function component but got \"null\"', {withoutStack: true});\n    });\n\n    it('throw error when rendering undefined', () => {\n      let UndefinedComponent = undefined;\n      expect(() => {\n        renderToString(<UndefinedComponent />);\n      }).toThrowError('Invalid element type, expected a string or a class/function component but got \"undefined\"', {withoutStack: true});\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/form.js",
    "content": "/* @jsx createElement */\n\nimport {createElement} from 'rax';\nimport {renderToString} from '../index';\n\ndescribe('form', () => {\n  describe('checkbox', function() {\n    it('a checkbox that is checked with an onChange', () => {\n      const str = renderToString(\n        <input type=\"checkbox\" checked={true} onChange={() => {}} />\n      );\n      expect(str).toBe('<input type=\"checkbox\" checked>');\n    });\n\n    it('a checkbox that is checked with disabled', () => {\n      const str = renderToString(\n        <input type=\"checkbox\" checked={true} disabled={true} />\n      );\n      expect(str).toBe('<input type=\"checkbox\" checked disabled>');\n    });\n\n    it('a checkbox that is checked and no onChange/disabled', () => {\n      const str = renderToString(\n        <input type=\"checkbox\" checked={true} />\n      );\n      expect(str).toBe('<input type=\"checkbox\" checked>');\n    });\n\n    it('a checkbox with defaultChecked', () => {\n      const str = renderToString(\n        <input type=\"checkbox\" defaultChecked={true} />\n      );\n      expect(str).toBe('<input type=\"checkbox\" checked>');\n    });\n\n    it('a checkbox checked overriding defaultChecked', () => {\n      const str = renderToString(\n        <input\n          type=\"checkbox\"\n          checked={true}\n          defaultChecked={false}\n          disabled={true}\n        />\n      );\n      expect(str).toBe('<input type=\"checkbox\" checked disabled>');\n    });\n\n    it('a checkbox checked overriding defaultChecked no matter the prop order', () => {\n      const str = renderToString(\n        <input\n          type=\"checkbox\"\n          defaultChecked={false}\n          checked={true}\n          disabled={true}\n        />\n      );\n      expect(str).toBe('<input type=\"checkbox\" checked disabled>');\n    });\n  });\n\n  describe('input', function() {\n    it('an input with a value and an onChange', () => {\n      const str = renderToString(\n        <input value=\"foo\" onChange={() => {}} />\n      );\n      expect(str).toBe('<input value=\"foo\">');\n    });\n\n    it('an input with a value and readOnly', () => {\n      const str = renderToString(\n        <input value=\"foo\" readOnly={true} />\n      );\n      expect(str).toBe('<input value=\"foo\" readOnly>');\n    });\n\n    it('an input with a value and no onChange/readOnly', () => {\n      const str = renderToString(\n        <input value=\"foo\" />\n      );\n      expect(str).toBe('<input value=\"foo\">');\n    });\n\n    it('an input with a defaultValue', () => {\n      const str = renderToString(\n        <input defaultValue=\"foo\" />\n      );\n      expect(str).toBe('<input value=\"foo\">');\n    });\n\n    it('an input value overriding defaultValue', () => {\n      const str = renderToString(\n        <input value=\"foo\" defaultValue=\"bar\" readOnly={true} />\n      );\n      expect(str).toBe('<input value=\"foo\" readOnly>');\n    });\n\n    it('an input value overriding defaultValue no matter the prop order', () => {\n      const str = renderToString(\n        <input defaultValue=\"bar\" value=\"foo\" readOnly={true} />\n      );\n      expect(str).toBe('<input value=\"foo\" readOnly>');\n    });\n\n    it('an zero input value overriding defaultValue', () => {\n      const str = renderToString(\n        <input defaultValue={9} value={0} readOnly={true} />\n      );\n      expect(str).toBe('<input value=\"0\" readOnly>');\n    });\n  });\n\n  describe('select', function() {\n    let options;\n    beforeEach(() => {\n      options = [\n        <option key={1} value=\"foo\" id=\"foo\">\n          Foo\n        </option>,\n        <option key={2} value=\"bar\" id=\"bar\">\n          Bar\n        </option>\n      ];\n    });\n\n    it('a select with a value and an onChange', () => {\n      const str = renderToString(\n        <select value=\"bar\" onChange={() => {}}>\n          {options}\n        </select>\n      );\n      expect(str).toBe('<select value=\"bar\"><option value=\"foo\" id=\"foo\">Foo</option><option value=\"bar\" id=\"bar\">Bar</option></select>');\n    });\n\n    it('a select value overriding defaultValue', () => {\n      const str = renderToString(\n        <select value=\"bar\" defaultValue=\"baz\" readOnly={true}>\n          {options}\n        </select>\n      );\n      expect(str).toBe('<select value=\"bar\" readOnly><option value=\"foo\" id=\"foo\">Foo</option><option value=\"bar\" id=\"bar\">Bar</option></select>');\n    });\n\n    it('a select option with flattened children', () => {\n      const str = renderToString(\n        <select value=\"bar\">\n          <option value=\"bar\">A {'B'}</option>\n        </select>\n      );\n      expect(str).toBe('<select value=\"bar\"><option value=\"bar\">A <!--|-->B</option></select>');\n    });\n  });\n\n  describe('textarea', function() {\n    it('a textarea with an onChange', () => {\n      const str = renderToString(\n        <textarea onChange={() => {}} />\n      );\n      expect(str).toBe('<textarea></textarea>');\n    });\n\n    it('a textarea with and readOnly', () => {\n      const str = renderToString(\n        <textarea readOnly={true} />\n      );\n      expect(str).toBe('<textarea readOnly></textarea>');\n    });\n\n    it('a textarea with a value and no onChange/readOnly', () => {\n      const str = renderToString(\n        <textarea />\n      );\n      expect(str).toBe('<textarea></textarea>');\n    });\n  });\n\n  describe('progress', function() {\n    it('prop with null value', () => {\n      const str = renderToString(\n        <progress value={null} />\n      );\n      expect(str).toBe('<progress></progress>');\n    });\n\n    it('prop with number value', () => {\n      const str = renderToString(\n        <progress value={50} />\n      );\n      expect(str).toBe('<progress value=\"50\"></progress>');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/fragment.js",
    "content": "/* @jsx createElement */\n\nimport {createElement, Fragment} from 'rax';\nimport {renderToString} from '../index';\n\ndescribe('Fragment', () => {\n  it('a fragment with one child', () => {\n    const str = renderToString(\n      <Fragment>\n        <div>text1</div>\n      </Fragment>\n    );\n    expect(str).toBe('<div>text1</div>');\n  });\n\n  it('a fragment with several children', () => {\n    let Header = props => {\n      return <p>header</p>;\n    };\n    let Footer = props => {\n      return (\n        <Fragment>\n          <h2>footer</h2>\n          <h3>about</h3>\n        </Fragment>\n      );\n    };\n\n    const str = renderToString(\n      <Fragment>\n        <Header />\n        <div>text1</div>\n        <span>text2</span>\n        <Footer />\n      </Fragment>\n    );\n    expect(str).toBe('<p>header</p><div>text1</div><span>text2</span><h2>footer</h2><h3>about</h3>');\n  });\n\n  it('a nested fragment', () => {\n    const str = renderToString(\n      <Fragment>\n        <Fragment>\n          <div>text1</div>\n        </Fragment>\n        <span>text2</span>\n        <Fragment>\n          <Fragment>\n            <Fragment>\n              {null}\n              <p />\n            </Fragment>\n            {false}\n          </Fragment>\n        </Fragment>\n      </Fragment>,\n    );\n    expect(str).toBe('<div>text1</div><span>text2</span><!-- _ --><p></p><!-- _ -->');\n  });\n\n  it('an empty fragment', () => {\n    const str = renderToString(\n      <Fragment />\n    );\n    expect(str).toBe('<!-- _ -->');\n  });\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/hooks.js",
    "content": "/* @jsx createElement */\n\nimport {createElement, Component, useState, useReducer, useMemo, forwardRef, createRef, useRef, useEffect, useCallback, useImperativeHandle, useLayoutEffect, createContext, useContext} from 'rax';\nimport {renderToString} from '../index';\n\nfunction Text(props) {\n  return <span>{props.text}</span>;\n}\n\ndescribe('hooks', () => {\n  describe('useState', () => {\n    it('basic render', () => {\n      function Counter(props) {\n        const [count] = useState(0);\n        return <span>Count: {count}</span>;\n      }\n\n      let str = renderToString(<Counter />);\n      expect(str).toBe('<span>Count: <!--|-->0</span>');\n    });\n\n    it('lazy state initialization', () => {\n      function Counter(props) {\n        const [count] = useState(() => {\n          return 0;\n        });\n        return <span>Count: {count}</span>;\n      }\n\n      let str = renderToString(<Counter />);\n      expect(str).toBe('<span>Count: <!--|-->0</span>');\n    });\n\n    it('should ignore setCount on the server', () => {\n      function Counter() {\n        let [count, setCount] = useState(0);\n        if (count < 3) {\n          setCount(count + 1);\n        }\n        return <span>Count: {count}</span>;\n      }\n\n      let str = renderToString(<Counter />);\n      expect(str).toBe('<span>Count: <!--|-->0</span>');\n    });\n  });\n\n  describe('useReducer', () => {\n    it('render with initial state', () => {\n      function reducer(state, action) {\n        return action === 'increment' ? state + 1 : state;\n      }\n\n      function Counter() {\n        let [count] = useReducer(reducer, 0);\n        return <Text text={count} />;\n      }\n\n      let str = renderToString(<Counter />);\n      expect(str).toBe('<span>0</span>');\n    });\n\n    it('lazy initialization', () => {\n      function reducer(state, action) {\n        return action === 'increment' ? state + 1 : state;\n      }\n      function Counter() {\n        let [count] = useReducer(reducer, 0, c => c + 1);\n        return <Text text={count} />;\n      }\n\n      let str = renderToString(<Counter />);\n      expect(str).toBe('<span>1</span>');\n    });\n\n    it('should ignore dispatch on the server', () => {\n      function reducer(state, action) {\n        return action === 'increment' ? state + 1 : state;\n      }\n      function Counter() {\n        let [count, dispatch] = useReducer(reducer, 0);\n        if (count < 3) {\n          dispatch('increment');\n        }\n\n        return <Text text={count} />;\n      }\n\n      let str = renderToString(<Counter />);\n      expect(str).toBe('<span>0</span>');\n    });\n  });\n\n  describe('useMemo', () => {\n    it('basic render', () => {\n      function CapitalizedText(props) {\n        const text = props.text;\n        const capitalizedText = useMemo(\n          () => {\n            return text.toUpperCase();\n          },\n          [text],\n        );\n        return <Text text={capitalizedText} />;\n      }\n\n      let str = renderToString(<CapitalizedText text=\"hello\" />);\n      expect(str).toBe('<span>HELLO</span>');\n    });\n\n    it('if no inputs are provided', () => {\n      function CapitalizedText(props) {\n        const computed = useMemo(props.compute);\n        return <Text text={computed} />;\n      }\n\n      function computeA() {\n        return 'A';\n      }\n\n      let str = renderToString(<CapitalizedText compute={computeA} />);\n      expect(str).toBe('<span>A</span>');\n    });\n  });\n\n  describe('useRef', () => {\n    it('basic render', () => {\n      function Counter() {\n        const count = useRef(0);\n        return <span>Count: {count.current}</span>;\n      }\n\n      let str = renderToString(<Counter />);\n      expect(str).toBe('<span>Count: <!--|-->0</span>');\n    });\n  });\n\n  describe('useEffect', () => {\n    it('should ignore effects on the server', () => {\n      function Counter(props) {\n        useEffect(() => {\n          throw new Error('should not be invoked');\n        });\n        return <span>Count: {props.count}</span>;\n      }\n\n      let str = renderToString(<Counter count={0} />);\n      expect(str).toBe('<span>Count: <!--|-->0</span>');\n    });\n  });\n\n  describe('useCallback', () => {\n    it('should ignore callbacks on the server', () => {\n      function Counter(props) {\n        useCallback(() => {\n          throw new Error('should not be invoked');\n        });\n        return <span>Count: {props.count}</span>;\n      }\n\n      let str = renderToString(<Counter count={0} />);\n      expect(str).toBe('<span>Count: <!--|-->0</span>');\n    });\n\n    it('should support render time callbacks', () => {\n      function Counter(props) {\n        const renderCount = useCallback(increment => {\n          return 'Count: ' + (props.count + increment);\n        });\n        return <span>{renderCount(3)}</span>;\n      }\n\n      let str = renderToString(<Counter count={2} />);\n      expect(str).toBe('<span>Count: 5</span>');\n    });\n  });\n\n  describe('useImperativeHandle', () => {\n    it('should not be invoked on the server', () => {\n      function Counter(props, ref) {\n        useImperativeHandle(ref, () => {\n          throw new Error('should not be invoked');\n        });\n        return <span>{props.label + ': ' + ref.current}</span>;\n      }\n\n      Counter = forwardRef(Counter);\n      const counter = createRef();\n      counter.current = 0;\n\n      let str = renderToString(<Counter label=\"Count\" ref={counter} />);\n      expect(str).toBe('<span>Count: 0</span>');\n    });\n  });\n\n  describe('useLayoutEffect', () => {\n    it('should not be invoked on the server', () => {\n      function Counter() {\n        useLayoutEffect(() => {\n          throw new Error('should not be invoked');\n        });\n\n        return <span>Count: 0</span>;\n      }\n\n      let str = renderToString(<Counter />);\n      expect(str).toBe('<span>Count: 0</span>');\n    });\n  });\n\n  describe('useContext', () => {\n    it('can use the same context multiple times in the same function', () => {\n      const Context = createContext({foo: 0, bar: 0, baz: 0});\n\n      function Provider(props) {\n        return (\n          <Context.Provider\n            value={{foo: props.foo, bar: props.bar, baz: props.baz}}>\n            {props.children}\n          </Context.Provider>\n        );\n      }\n\n      function FooAndBar() {\n        const {foo} = useContext(Context);\n        const {bar} = useContext(Context);\n        return <Text text={`Foo: ${foo}, Bar: ${bar}`} />;\n      }\n\n      function Baz() {\n        const {baz} = useContext(Context);\n        return <Text text={'Baz: ' + baz} />;\n      }\n\n      class Indirection extends Component {\n        render() {\n          return this.props.children;\n        }\n      }\n\n      function App(props) {\n        return (\n          <div>\n            <Provider foo={props.foo} bar={props.bar} baz={props.baz}>\n              <Indirection>\n                <Indirection>\n                  <FooAndBar />\n                </Indirection>\n                <Indirection>\n                  <Baz />\n                </Indirection>\n              </Indirection>\n            </Provider>\n          </div>\n        );\n      }\n\n      let str = renderToString(<App foo={1} bar={3} baz={5} />);\n      expect(str).toBe('<div><span>Foo: 1, Bar: 3</span><span>Baz: 5</span></div>');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/lifecycle.js",
    "content": "/* @jsx createElement */\n\nimport {createElement, Component} from 'rax';\nimport {renderToString} from '../index';\n\ndescribe('lifecycle', () => {\n  it('should only execute certain lifecycle methods', () => {\n    const lifecycle = [];\n\n    class TestComponent extends Component {\n      constructor(props) {\n        super(props);\n        lifecycle.push('getInitialState');\n        this.state = {name: 'TestComponent'};\n      }\n\n      componentWillMount() {\n        lifecycle.push('componentWillMount');\n      }\n\n      componentDidMount() {\n        lifecycle.push('componentDidMount');\n      }\n\n      render() {\n        lifecycle.push('render');\n        return <span>Component name: {this.state.name}</span>;\n      }\n\n      componentDidUpdate() {\n        lifecycle.push('componentDidUpdate');\n      }\n\n      shouldComponentUpdate() {\n        lifecycle.push('shouldComponentUpdate');\n      }\n\n      UNSAFE_componentWillReceiveProps() {\n        lifecycle.push('componentWillReceiveProps');\n      }\n\n      componentWillUnmount() {\n        lifecycle.push('componentWillUnmount');\n      }\n    }\n\n    const response = renderToString(<TestComponent />);\n\n    expect(response).toBe('<span>Component name: <!--|-->TestComponent</span>');\n\n    expect(lifecycle).toEqual([\n      'getInitialState',\n      'componentWillMount',\n      'render',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/memo.js",
    "content": "/* @jsx createElement */\n\nimport {createElement, memo} from 'rax';\nimport {renderToString} from '../index';\n\ndescribe('memo', () => {\n  it('comparator functions are not invoked on the server', () => {\n    let renderCounter1 = 0;\n    let renderCounter2 = 0;\n\n    function App(props) {\n      renderCounter1++;\n      return <span>{props.value}</span>;\n    }\n\n    App = memo(App, (oldProps, newProps) => {\n      throw new Error('should not be invoked');\n    });\n\n    function Outer(props) {\n      renderCounter2++;\n      return <App value={props.value} />;\n    }\n\n    renderToString(<Outer value={1} />);\n    expect(renderCounter1).toEqual(1);\n    expect(renderCounter2).toEqual(1);\n\n    renderToString(<Outer value={2} />);\n    expect(renderCounter1).toEqual(2);\n    expect(renderCounter2).toEqual(2);\n\n    renderToString(<Outer value={2} />);\n    expect(renderCounter1).toEqual(3);\n    expect(renderCounter2).toEqual(3);\n  });\n});\n\n"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/refs.js",
    "content": "/* @jsx createElement */\n\nimport {createElement} from 'rax';\nimport {renderToString} from '../index';\n\ndescribe('refs', () => {\n  it('should ignore ref on server', () => {\n    function MyComponent() {\n      return <div ref=\"myDiv\" />;\n    }\n\n    const str = renderToString(<MyComponent />);\n    expect(str).toBe('<div></div>');\n  });\n\n  it('should not run ref code on server', () => {\n    let refCount = 0;\n\n    function MyComponent() {\n      return <div ref={e => refCount++} />;\n    }\n\n    const str = renderToString(<MyComponent />);\n    expect(str).toBe('<div></div>');\n    expect(refCount).toBe(0);\n  });\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/renderToString.js",
    "content": "/* @jsx createElement */\n\nimport {createElement, Component, useState, useEffect, createContext, useContext, useReducer} from 'rax';\nimport {renderToString} from '../index';\n\ndescribe('renderToString', () => {\n  it('render plain component', () => {\n    class MyComponent {\n      render() {\n        return <div />;\n      }\n    }\n\n    let str = renderToString(<MyComponent />);\n    expect(str).toBe('<div></div>');\n  });\n\n  it('render return array element', () => {\n    class MyComponent {\n      render() {\n        return [\n          <div />,\n          <div />,\n          'hi'\n        ];\n      }\n    }\n\n    let str = renderToString(<MyComponent />);\n    expect(str).toBe('<div></div><div></div>hi');\n  });\n\n  it('render return string', () => {\n    class MyComponent {\n      render() {\n        return 'hi';\n      }\n    }\n\n    let str = renderToString(<MyComponent />);\n    expect(str).toBe('hi');\n  });\n\n  it('render stateless component', () => {\n    function MyComponent(props, context) {\n      return <div name={props.name} />;\n    }\n\n    let str = renderToString(<MyComponent name=\"foo\" />);\n    expect(str).toBe('<div name=\"foo\"></div>');\n  });\n\n  it('render with dangerouslySetInnerHTML', () => {\n    function MyComponent(props, context) {\n      return <div dangerouslySetInnerHTML={{__html: '<hr>'}} />;\n    }\n\n    let str = renderToString(<MyComponent />);\n    expect(str).toBe('<div><hr></div>');\n  });\n\n  it('render with defaultValue', () => {\n    function MyComponent(props, context) {\n      return <input defaultValue={'foo'} />;\n    }\n\n    let str = renderToString(<MyComponent />);\n    expect(str).toBe('<input value=\"foo\">');\n  });\n\n  it('render with defaultChecked', () => {\n    function MyComponent(props, context) {\n      return <input type=\"radio\" defaultChecked=\"checked\" />;\n    }\n\n    let str = renderToString(<MyComponent />);\n    expect(str).toBe('<input type=\"radio\" checked>');\n  });\n\n  it('render with state hook', () => {\n    function MyComponent(props) {\n      const [name, setName] = useState(props.name);\n\n      return (\n        <h1> Hello {name}</h1>\n      );\n    };\n\n    let str = renderToString(<MyComponent name=\"rax\" />);\n    expect(str).toBe('<h1> Hello <!--|-->rax</h1>');\n  });\n\n  it('render with effect hook', () => {\n    function MyComponent(props) {\n      const [name, setName] = useState(props.name);\n\n      useEffect(() => {\n        // ...\n      });\n\n      return (\n        <h1> Hello {name}</h1>\n      );\n    };\n\n    let str = renderToString(<MyComponent name=\"rax\" />);\n    expect(str).toBe('<h1> Hello <!--|-->rax</h1>');\n  });\n\n  it('render with Context.Provider', () => {\n    const ThemeContext = createContext('light');\n\n    function MyContext() {\n      return (\n        <ThemeContext.Provider value={'dark'}>\n          <MyComponent />\n        </ThemeContext.Provider>\n      );\n    };\n\n    function MyComponent() {\n      const value = useContext(ThemeContext);\n      return (\n        <div>Current theme is {value}.</div>\n      );\n    };\n\n    let str = renderToString(<MyContext />);\n    expect(str).toBe('<div>Current theme is <!--|-->dark<!--|-->.</div>');\n  });\n\n\n  it('render with Context.Consumer', () => {\n    const ThemeContext = createContext('light');\n\n    function MyContext() {\n      return (\n        <ThemeContext.Provider value={'dark'}>\n          <MyComponent />\n        </ThemeContext.Provider>\n      );\n    };\n\n    function MyComponent() {\n      return (\n        <ThemeContext.Consumer>\n          {value => <div>Current theme is {value}.</div>}\n        </ThemeContext.Consumer>\n      );\n    };\n\n    let str = renderToString(<MyContext />);\n    expect(str).toBe('<div>Current theme is <!--|-->dark<!--|-->.</div>');\n  });\n\n  it('render with context hook', () => {\n    const NumberContext = createContext(5);\n\n    function MyComponent() {\n      const value = useContext(NumberContext);\n\n      return (\n        <div>The answer is {value}.</div>\n      );\n    };\n\n    let str = renderToString(<MyComponent />);\n    expect(str).toBe('<div>The answer is <!--|-->5<!--|-->.</div>');\n  });\n\n  it('render with reducer hook', () => {\n    const initialState = {count: 0};\n\n    function reducer(state, action) {\n      switch (action.type) {\n        case 'reset':\n          return initialState;\n        case 'increment':\n          return {count: state.count + 1};\n        case 'decrement':\n          return {count: state.count - 1};\n        default:\n        // A reducer must always return a valid state.\n        // Alternatively you can throw an error if an invalid action is dispatched.\n          return state;\n      }\n    }\n\n    function MyComponent({initialCount}) {\n      const [state] = useReducer(reducer, {count: initialCount});\n      return (\n        <div>Count: {state.count}</div>\n      );\n    }\n\n    let str = renderToString(<MyComponent initialCount={0} />);\n    expect(str).toBe('<div>Count: <!--|-->0</div>');\n  });\n\n  it('render with pre compiled html and attrs', () => {\n    function View(props) {\n      return (\n        <div>{props.name}</div>\n      );\n    }\n\n    function MyComponent(props) {\n      // <div className=\"container\" title={props.title}>\n      //   <div>hello</div>\n      //   <View name={props.name} />\n      //   {props.version}\n      // </div>\n\n      return (\n        [{\n          __html: '<div class=\"container\"'\n        }, {\n          __attrs: {\n            title: props.title\n          }\n        }, {\n          __html: '>'\n        }, [{\n          __html: '<div>'\n        }, 'hello', {\n          __html: '</div>'\n        }], createElement(View, {\n          name: props.name\n        }), props.version, {\n          __html: '</div>'\n        }]\n      );\n    }\n\n    let str = renderToString(<MyComponent title=\"welcome\" name=\"rax\" version=\"1.0\" />);\n    expect(str).toBe('<div class=\"container\" title=\"welcome\"><div>hello</div><div>rax</div>1.0</div>');\n  });\n\n  it('render pre compiled html with state hook', () => {\n    function MyComponent(props) {\n      const [name, setName] = useState(props.name);\n\n      return [\n        {\n          __html: '<h1>Hello ',\n        },\n        name,\n        {\n          __html: '</h1>'\n        }\n      ];\n    };\n\n    let str = renderToString(<MyComponent name=\"rax\" />);\n    expect(str).toBe('<h1>Hello rax</h1>');\n  });\n\n  it('render pre compiled html with context', () => {\n    const ThemeContext = createContext('light');\n\n    function MyContext() {\n      return (\n        <ThemeContext.Provider value={'dark'}>\n          <MyComponent />\n        </ThemeContext.Provider>\n      );\n    };\n\n    function MyComponent() {\n      const value = useContext(ThemeContext);\n      return [\n        {\n          __html: '<div>Current theme is ',\n        },\n        value,\n        {\n          __html: '</div>'\n        }\n      ];\n    };\n\n    let str = renderToString(<MyContext />);\n    expect(str).toBe('<div>Current theme is dark</div>');\n  });\n\n\n  it('render two Consumer and one use default context value', function() {\n    const ThemeContext = createContext('light');\n\n    function MyContext() {\n      return (\n        <ThemeContext.Provider value={'dark'}>\n          <MyComponent />\n        </ThemeContext.Provider>\n      );\n    };\n\n    function MyComponent() {\n      return (\n        <ThemeContext.Consumer>\n          {value => <div>{value}</div>}\n        </ThemeContext.Consumer>\n      );\n    };\n\n    function MyContext2() {\n      return (\n        <ThemeContext.Consumer>\n          {value => <div>{value}</div>}\n        </ThemeContext.Consumer>\n      );\n    }\n\n    function App() {\n      return (\n        [\n          <MyContext />,\n          <MyContext2 />\n        ]\n      );\n    };\n\n    const str = renderToString(<App />);\n    expect(str).toBe('<div>dark</div><div>light</div>');\n  });\n\n  it('render one Consumer use default context value', function() {\n    const ThemeContext = createContext('light');\n\n    function MyContext() {\n      return (\n        <ThemeContext.Provider value={'dark'} />\n      );\n    };\n\n    function MyContext2() {\n      return (\n        <ThemeContext.Consumer>\n          {value => <div>{value}</div>}\n        </ThemeContext.Consumer>\n      );\n    }\n\n    function App() {\n      return (\n        [\n          <MyContext />,\n          <MyContext2 />\n        ]\n      );\n    };\n\n    const str = renderToString(<App />);\n    expect(str).toBe('<!-- _ --><div>light</div>');\n  });\n\n  it('should catch error with componentDidCatch', function() {\n    class ErrorBoundary extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      componentDidCatch(error, errorInfo) {\n        // log error\n      }\n\n      render() {\n        return this.props.children;\n      }\n    }\n\n    function MyWidget() {\n      throw new Error('widget error');\n    }\n\n    function App() {\n      return (\n        <div>\n          <ErrorBoundary>\n            <MyWidget />\n          </ErrorBoundary>\n        </div>\n      );\n    };\n\n    const str = renderToString(<App />);\n    expect(str).toBe('<div><!--ERROR--></div>');\n  });\n\n  it('should call componentDidCatch when catch error', function() {\n    const mockFn = jest.fn();\n    class ErrorBoundary extends Component {\n      constructor(props) {\n        super(props);\n      }\n\n      componentDidCatch(error, errorInfo) {\n        mockFn();\n      }\n\n      render() {\n        return this.props.children;\n      }\n    }\n\n    function MyWidget() {\n      throw new Error('widget error');\n    }\n\n    function App() {\n      return (\n        <div>\n          <ErrorBoundary>\n            <MyWidget />\n          </ErrorBoundary>\n        </div>\n      );\n    };\n\n    const str = renderToString(<App />);\n    expect(mockFn).toHaveBeenCalled();\n    expect(str).toBe('<div><!--ERROR--></div>');\n  });\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/styles.js",
    "content": "/* @jsx createElement */\n\nimport {createElement} from 'rax';\nimport {renderToString} from '../index';\n\ndescribe('inline styles', () => {\n  describe('basic', () => {\n    it('render simple styles', () => {\n      let str = renderToString(\n        <div style={{color: 'red', width: '30px'}} />\n      );\n      expect(str).toBe('<div style=\"color:red;width:30px;\"></div>');\n    });\n\n    it('relevant styles with px', () => {\n      let str = renderToString(\n        <div\n          style={{\n            left: 0,\n            margin: 16,\n            opacity: 0.5,\n            padding: '4px',\n          }}\n        />\n      );\n      expect(str).toBe('<div style=\"left:0px;margin:16px;opacity:0.5;padding:4px;\"></div>');\n    });\n\n    it('custom properties', () => {\n      let str = renderToString(\n        <div style={{'foo': 5}} />\n      );\n      expect(str).toBe('<div style=\"foo:5px;\"></div>');\n    });\n\n    it('camel cased custom properties', () => {\n      let str = renderToString(\n        <div style={{'someColor': '#000000'}} />\n      );\n      expect(str).toBe('<div style=\"some-color:#000000;\"></div>');\n    });\n\n    it('no undefined styles', () => {\n      let str = renderToString(\n        <div style={{color: undefined, width: '30px'}} />\n      );\n      expect(str).toBe('<div style=\"width:30px;\"></div>');\n    });\n\n    it('no null styles', () => {\n      let str = renderToString(\n        <div style={{color: null, width: '30px'}} />\n      );\n      expect(str).toBe('<div style=\"width:30px;\"></div>');\n    });\n\n    it('empty styles', () => {\n      let str = renderToString(\n        <div style={{color: null, width: null}} />\n      );\n      expect(str).toBe('<div style=\"\"></div>');\n    });\n\n    it('unitless-number rules with prefixes', () => {\n      let str = renderToString(\n        <div\n          style={{\n            lineClamp: 10,\n            WebkitLineClamp: 10,\n            MozFlexGrow: 10,\n            msFlexGrow: 10,\n            msGridRow: 10,\n            msGridRowEnd: 10,\n            msGridRowSpan: 10,\n            msGridRowStart: 10,\n            msGridColumn: 10,\n            msGridColumnEnd: 10,\n            msGridColumnSpan: 10,\n            msGridColumnStart: 10,\n          }}\n        />\n      );\n      expect(str).toBe('<div style=\"line-clamp:10;-webkit-line-clamp:10;-moz-flex-grow:10;ms-flex-grow:10;ms-grid-row:10;ms-grid-row-end:10;ms-grid-row-span:10;ms-grid-row-start:10;ms-grid-column:10;ms-grid-column-end:10;ms-grid-column-span:10;ms-grid-column-start:10;\"></div>');\n    });\n\n    it('style with lineHeight', () => {\n      const styles = {\n        container: {\n          lineHeight: 1\n        },\n        text: {\n          lineHeight: '75rpx'\n        }\n      };\n\n      function MyComponent(props, context) {\n        return (\n          <div style={styles.container}>\n            <p style={styles.text}>Hello</p>\n          </div>\n        );\n      }\n\n      const str = renderToString(<MyComponent />);\n      expect(str).toBe('<div style=\"line-height:1;\"><p style=\"line-height:10vw;\">Hello</p></div>');\n    });\n\n    it('style with unitless property', () => {\n      const style = {\n        flex: 1,\n        fontSize: 16,\n        width: '100%'\n      };\n\n      function MyComponent(props, context) {\n        return <div style={style} />;\n      }\n\n      let str = renderToString(<MyComponent />);\n      expect(str).toBe('<div style=\"flex:1;font-size:16px;width:100%;\"></div>');\n    });\n\n    it('style with fontWeight', () => {\n      const styles = {\n        numericalProperty: {\n          fontWeight: 600,\n        },\n        stringifyProperty: {\n          fontWeight: '600'\n        },\n        propertyWithKeyWord: {\n          fontWeight: 'bold'\n        }\n      };\n\n      function MyComponent(props, context) {\n        return (\n          <div>\n            <div style={styles.numericalProperty}></div>\n            <div style={styles.stringifyProperty}></div>\n            <div style={styles.propertyWithKeyWord}></div>\n          </div>\n        );\n      }\n\n      let str = renderToString(<MyComponent />);\n      expect(str).toBe('<div><div style=\"font-weight:600;\"></div><div style=\"font-weight:600;\"></div><div style=\"font-weight:bold;\"></div></div>');\n    });\n  });\n\n  describe('rpx', () => {\n    it('style with rpx', () => {\n      const style = {\n        flex: 1,\n        fontSize: '16rpx',\n        width: '100%'\n      };\n\n      const str = renderToString(<div style={style} />);\n      expect(str).toBe('<div style=\"flex:1;font-size:2.1333vw;width:100%;\"></div>');\n    });\n\n    it('set default unit as rpx', () => {\n      const styles = {\n        container: {\n          lineHeight: 1\n        },\n        text: {\n          fontSize: 75\n        }\n      };\n\n      function MyComponent(props, context) {\n        return (\n          <div style={styles.container}>\n            <p style={styles.text}>Hello</p>\n          </div>\n        );\n      }\n\n      const str = renderToString(<MyComponent />, {\n        defaultUnit: 'rpx'\n      });\n      expect(str).toBe('<div style=\"line-height:1;\"><p style=\"font-size:10vw;\">Hello</p></div>');\n    });\n\n    it('render transform value with rpx', () => {\n      const style = {\n        transform: 'translate3d(-200rpx, 0, 0)'\n      };\n\n      const str = renderToString(<div style={style} />);\n      expect(str).toBe('<div style=\"transform:translate3d(-26.6667vw, 0, 0);\"></div>');\n    });\n\n    it('render url() with rpx', () => {\n      const style = {\n        backgroundImage: 'url(\"abc2rpx\")'\n      };\n\n      const str = renderToString(<div style={style} />);\n      expect(str).toBe('<div style=\"background-image:url(\\\"abc2rpx\\\");\"></div>');\n    });\n  });\n\n  it('render style with array value', () => {\n    const styles = {\n      title: {\n        fontSize: 16,\n      },\n      container: {\n        flex: 1,\n        width: '100%'\n      }\n    };\n\n    function MyComponent(props, context) {\n      return <div style={[styles.container, styles.title]} />;\n    }\n\n    const str = renderToString(<MyComponent />);\n    expect(str).toBe('<div style=\"flex:1;width:100%;font-size:16px;\"></div>');\n  });\n\n  it('render items with same style', () => {\n    const style = {\n      color: '#f00',\n      fontSize: '16px'\n    };\n\n    function MyComponent(props, context) {\n      const data = [1, 2];\n      return (\n        <div>\n          {\n            data.map((_, i) => <div key={i} style={style}>hello</div>)\n          }\n        </div>\n      );\n    }\n\n    const str = renderToString(<MyComponent />);\n    expect(str).toBe('<div><div style=\"color:#f00;font-size:16px;\">hello</div><div style=\"color:#f00;font-size:16px;\">hello</div></div>');\n  });\n\n  it('render items with a base style', () => {\n    const style = {\n      color: '#f00',\n      fontSize: '16px'\n    };\n\n    function MyComponent(props, context) {\n      const data = [1, 2];\n      return (\n        <div>\n          {\n            data.map((item, index) => <div key={index} style={{...style, fontSize: index + 'px'}}>hello</div>)\n          }\n        </div>\n      );\n    }\n\n    const str = renderToString(<MyComponent />);\n    expect(str).toBe('<div><div style=\"color:#f00;font-size:0px;\">hello</div><div style=\"color:#f00;font-size:1px;\">hello</div></div>');\n  });\n\n  it('render items with change to base style', () => {\n    const style = {\n      color: '#f00',\n      fontSize: '16px'\n    };\n\n    function MyComponent(props, context) {\n      const data = [1, 2];\n      return (\n        <div>\n          {\n            data.map((item, index) => {\n              // after map, style.fontSize will be 1px\n              style.fontSize = index + 'px';\n              return <div key={index} style={style}>hello</div>;\n            })\n          }\n        </div>\n      );\n    }\n\n    const str = renderToString(<MyComponent />);\n    expect(str).toBe('<div><div style=\"color:#f00;font-size:1px;\">hello</div><div style=\"color:#f00;font-size:1px;\">hello</div></div>');\n  });\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/__tests__/url.js",
    "content": "/* @jsx createElement */\n\nimport {createElement} from 'rax';\nimport {renderToString} from '../index';\n\ndescribe('url', () => {\n  it('a http link with the word javascript in it', () => {\n    const str = renderToString(\n      <a href=\"http://javascript:0/thisisfine\">Click me</a>\n    );\n    expect(str).toBe('<a href=\"http://javascript:0/thisisfine\">Click me</a>');\n  });\n\n  it('a javascript protocol href', () => {\n    const str = renderToString(\n      <div>\n        <a href=\"javascript:notfine\">p0wned</a>\n        <a href=\"javascript:notfineagain\">p0wned again</a>\n      </div>,\n    );\n    expect(str).toBe('<div><a href=\"javascript:notfine\">p0wned</a><a href=\"javascript:notfineagain\">p0wned again</a></div>');\n  });\n\n  it('a javascript protocol with leading spaces', () => {\n    const str = renderToString(\n      <a href={'  \\t \\u0000\\u001F\\u0003javascript\\n: notfine'}>p0wned</a>,\n    );\n    expect(str).toBe('<a href=\"  \\t \\u0000\\u001F\\u0003javascript\\n: notfine\">p0wned</a>');\n  });\n\n  it('a javascript protocol with intermediate new lines and mixed casing', () => {\n    const str = renderToString(\n      <a href={'\\t\\r\\n Jav\\rasCr\\r\\niP\\t\\n\\rt\\n:notfine'}>p0wned</a>,\n    );\n    expect(str).toBe('<a href=\"\\t\\r\\n Jav\\rasCr\\r\\niP\\t\\n\\rt\\n:notfine\">p0wned</a>');\n  });\n\n  it('a javascript protocol area href', () => {\n    const str = renderToString(\n      <map>\n        <area href=\"javascript:notfine\" />\n      </map>,\n    );\n    expect(str).toBe('<map><area href=\"javascript:notfine\"></map>');\n  });\n\n  it('a javascript protocol form action', () => {\n    const str = renderToString(\n      <form action=\"javascript:notfine\">p0wned</form>\n    );\n    expect(str).toBe('<form action=\"javascript:notfine\">p0wned</form>');\n  });\n\n  it('a javascript protocol button formAction', () => {\n    const str = renderToString(\n      <input formAction=\"javascript:notfine\" />\n    );\n    expect(str).toBe('<input formAction=\"javascript:notfine\">');\n  });\n\n  it('a javascript protocol input formAction', () => {\n    const str = renderToString(\n      <button formAction=\"javascript:notfine\">p0wned</button>,\n    );\n    expect(str).toBe('<button formAction=\"javascript:notfine\">p0wned</button>');\n  });\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/attribute.js",
    "content": "// A simple string attribute.\n// Attributes that aren't in the whitelist are presumed to have this type.\nexport const STRING = 1;\n\n// A string attribute that accepts booleans in Rax. In HTML, these are called\n// \"enumerated\" attributes with \"true\" and \"false\" as possible values.\n// When true, it should be set to a \"true\" string.\n// When false, it should be set to a \"false\" string.\nexport const BOOLEANISH_STRING = 2;\n\n// A real boolean attribute.\n// When true, it should be present (set either to an empty string or its name).\n// When false, it should be omitted.\nexport const BOOLEAN = 3;\n\n// An attribute that can be used as a flag as well as with a value.\n// When true, it should be present (set either to an empty string or its name).\n// When false, it should be omitted.\n// For any other value, should be present with that value.\nexport const OVERLOADED_BOOLEAN = 4;\n\n// An attribute that must be numeric or parse as a numeric.\n// When falsy, it should be removed.\nexport const NUMERIC = 5;\n\n// An attribute that must be positive numeric or parse as a positive numeric.\n// When falsy, it should be removed.\nexport const POSITIVE_NUMERIC = 6;\n\nconst properties = {};\n\nexport function getPropertyInfo(prop) {\n  return properties[prop];\n}\n\nexport function shouldRemoveAttribute(prop, value) {\n  const propertyInfo = getPropertyInfo(prop);\n  const propType = propertyInfo ? propertyInfo.type : null;\n  const valueType = typeof value;\n\n  if (value === null || valueType === 'undefined') {\n    return true;\n  }\n\n  switch (valueType) {\n    case 'function':\n    case 'symbol':\n      return true;\n  }\n\n  if (propType !== null) {\n    switch (propType) {\n      case BOOLEAN:\n        return !value;\n      case OVERLOADED_BOOLEAN:\n        return value === false;\n      case NUMERIC:\n        return isNaN(value);\n      case POSITIVE_NUMERIC:\n        return isNaN(value) || value < 1;\n    }\n  }\n\n  return false;\n}\n\n[\n  'contentEditable',\n  'draggable',\n  'spellCheck',\n  'value'\n].forEach((name) => {\n  properties[name] = {\n    type: BOOLEANISH_STRING\n  };\n});\n\n[\n  'allowFullScreen',\n  'async',\n  'autoFocus',\n  'autoPlay',\n  'controls',\n  'default',\n  'defer',\n  'disabled',\n  'disablePictureInPicture',\n  'formNoValidate',\n  'hidden',\n  'loop',\n  'noModule',\n  'noValidate',\n  'open',\n  'playsInline',\n  'readOnly',\n  'required',\n  'reversed',\n  'scoped',\n  'seamless',\n  'itemScope',\n  'checked',\n  'multiple',\n  'muted',\n  'selected',\n].forEach((name) => {\n  properties[name] = {\n    type: BOOLEAN\n  };\n});\n\n[\n  'capture',\n  'download'\n].forEach((name) => {\n  properties[name] = {\n    type: OVERLOADED_BOOLEAN\n  };\n});\n\n[\n  'cols',\n  'rows',\n  'size',\n  'span',\n].forEach((name) => {\n  properties[name] = {\n    type: POSITIVE_NUMERIC\n  };\n});\n"
  },
  {
    "path": "packages/rax-server-renderer/src/index.js",
    "content": "import { shared } from 'rax';\nimport { convertUnit, setViewportWidth, setUnitPrecision, setTargetPlatform } from 'style-unit';\nimport { BOOLEAN, BOOLEANISH_STRING, OVERLOADED_BOOLEAN, shouldRemoveAttribute, getPropertyInfo } from './attribute';\nimport { UNITLESS_NUMBER_PROPS } from './CSSProperty';\n\nconst EMPTY_OBJECT = {};\n\nconst VOID_ELEMENTS = {\n  'area': true,\n  'base': true,\n  'br': true,\n  'col': true,\n  'embed': true,\n  'hr': true,\n  'img': true,\n  'input': true,\n  'link': true,\n  'meta': true,\n  'param': true,\n  'source': true,\n  'track': true,\n  'wbr': true\n};\n\nconst TEXT_SPLIT_COMMENT = '<!--|-->';\nconst ERROR_COMMENT = '<!--ERROR-->';\n\nconst ESCAPE_LOOKUP = {\n  '&': '&amp;',\n  '>': '&gt;',\n  '<': '&lt;',\n  '\"': '&quot;',\n  '\\'': '&#x27;',\n};\n\nconst ESCAPE_REGEXP = /[&><\"']/g;\nconst ESCAPE_TEST_REGEXP = /[&><\"']/;\nfunction escaper(match) {\n  return ESCAPE_LOOKUP[match];\n}\n\nfunction escapeText(text) {\n  if (!ESCAPE_TEST_REGEXP.test(text)) {\n    return text;\n  }\n\n  return String(text).replace(ESCAPE_REGEXP, escaper);\n}\n\nfunction merge(target) {\n  for (var i = 1; i < arguments.length; i++) {\n    var source = arguments[i];\n    for (var key in source) {\n      if (Object.prototype.hasOwnProperty.call(source, key)) {\n        target[key] = source[key];\n      }\n    }\n  }\n  return target;\n}\n\nconst DEFAULT_STYLE_OPTIONS = {\n  defaultUnit: 'px',\n  viewportWidth: 750,\n  unitPrecision: 4\n};\nconst UPPERCASE_REGEXP = /[A-Z]/g;\nconst NUMBER_REGEXP = /^[0-9]*$/;\nconst CSSPropCache = {};\n\nfunction styleToCSS(style, options = {}) {\n  let css = '';\n\n  if (Array.isArray(style)) {\n    style = style.reduce((prev, curr) => Object.assign(prev, curr), {});\n  }\n\n  // Use var avoid v8 warns \"Unsupported phi use of const or let variable\"\n  for (var prop in style) {\n    let val = style[prop];\n\n    if (val == null) {\n      continue;\n    }\n\n    // Handle unit for all numerical property, such as fontWeight: 600 / fontWeight: '600'\n    const type = typeof val;\n    if (type === 'number' || type === 'string' && NUMBER_REGEXP.test(val)) {\n      if (!UNITLESS_NUMBER_PROPS[prop]) {\n        val = val + options.defaultUnit;\n      }\n    }\n\n    if (typeof val === 'string' && val.indexOf('rpx') > -1) {\n      val = convertUnit(val);\n    }\n\n    prop = CSSPropCache[prop] ? CSSPropCache[prop] : CSSPropCache[prop] = prop.replace(UPPERCASE_REGEXP, '-$&').toLowerCase();\n    css = css + `${prop}:${val};`;\n  }\n\n  return css;\n}\n\nfunction createMarkupForProperty(prop, value, options) {\n  if (prop === 'children') {\n    // Ignore children prop\n    return '';\n  }\n\n  if (prop === 'style') {\n    return ` style=\"${styleToCSS(value, options)}\"`;\n  }\n\n  if (prop === 'className') {\n    return typeof value === 'string' ? ` class=\"${escapeText(value)}\"` : '';\n  }\n\n  if (prop === 'dangerouslySetInnerHTML') {\n    // Ignore innerHTML\n    return '';\n  }\n\n  if (shouldRemoveAttribute(prop, value)) {\n    return '';\n  }\n\n  const propInfo = getPropertyInfo(prop);\n  const propType = propInfo ? propInfo.type : null;\n  const valueType = typeof value;\n\n  if (propType === BOOLEAN || propType === OVERLOADED_BOOLEAN && value === true) {\n    return ` ${prop}`;\n  }\n\n  if (valueType === 'string') {\n    return ` ${prop}=\"${escapeText(value)}\"`;\n  }\n\n  if (valueType === 'number') {\n    return ` ${prop}=\"${String(value)}\"`;\n  }\n\n  if (valueType === 'boolean') {\n    if (propType === BOOLEANISH_STRING || prop.indexOf('data-') === 0 || prop.indexOf('aria-') === 0) {\n      return ` ${prop}=\"${value ? 'true' : 'false'}\"`;\n    }\n  }\n\n  return '';\n};\n\nfunction propsToString(props, options) {\n  let html = '';\n  for (var prop in props) {\n    var value = props[prop];\n\n    if (prop === 'defaultValue') {\n      if (props.value == null) {\n        prop = 'value';\n      } else {\n        continue;\n      }\n    }\n\n    if (prop === 'defaultChecked') {\n      if (!props.checked) {\n        prop = 'checked';\n      } else {\n        continue;\n      }\n    }\n\n    html = html + createMarkupForProperty(prop, value, options);\n  }\n\n  return html;\n}\n\nfunction checkContext(element) {\n  // Filter context by `contextTypes` or prevent pass context to child without `contextTypes`,\n  // need to distinguish context for passing to child and render, which will cause `Consumer` can not work correctly.\n  // The best way to get context is from the nearest parent provider, but it will increase the complexity of SSR.\n  if (element.contextTypes || element.childContextTypes) {\n    console.error(\n      'Warning: ' +\n      'The legacy \"contextTypes\" and \"childContextTypes\" API not working properly in server renderer, ' +\n      'use the new context API. ' +\n      `(Current: ${shared.Host.owner.__getName()})`\n    );\n  }\n}\n\nconst updater = {\n  setState(component, partialState, callback) {\n    if (partialState) {\n      if (!component._pendingState) {\n        component._pendingState = partialState;\n      } else {\n        merge(component._pendingState, partialState);\n      }\n    }\n  },\n  forceState(component, callback) {\n    // Noop\n  }\n};\n\n/**\n * Functional Reactive Component Class Wrapper\n */\nclass ServerReactiveComponent {\n  constructor(pureRender, ref) {\n    // A pure function\n    this._render = pureRender;\n    this._hookID = 0;\n    this._hooks = {};\n    // Handles store\n    this.didMount = [];\n    this.didUpdate = [];\n    this.willUnmount = [];\n\n    if (pureRender._forwardRef) {\n      this._forwardRef = ref;\n    }\n  }\n\n  getHooks() {\n    return this._hooks;\n  }\n\n  getHookID() {\n    return ++this._hookID;\n  }\n\n  useContext(context) {\n    const contextID = context._contextID;\n\n    if (this.context[contextID]) {\n      return this.context[contextID].getValue();\n    } else {\n      return context._defaultValue;\n    }\n  }\n\n  render() {\n    this._hookID = 0;\n    let children = this._render(this.props, this._forwardRef ? this._forwardRef : this.context);\n    return children;\n  }\n}\n\nfunction createInstance(element, context) {\n  const { type } = element;\n  const props = element.props || EMPTY_OBJECT;\n\n  let instance;\n\n  // class component\n  if (type.prototype && type.prototype.render) {\n    instance = new type(props, context); // eslint-disable-line new-cap\n    instance.props = props;\n    instance.context = context;\n    // Inject the updater into instance\n    instance.updater = updater;\n\n    if (instance.componentWillMount) {\n      instance.componentWillMount();\n\n      if (instance._pendingState) {\n        const state = instance.state;\n        const pending = instance._pendingState;\n\n        if (state == null) {\n          instance.state = pending;\n        } else {\n          for (var key in pending) {\n            state[key] = pending[key];\n          }\n        }\n        instance._pendingState = null;\n      }\n    }\n  } else {\n    const ref = element.ref;\n    instance = new ServerReactiveComponent(type, ref);\n    instance.props = props;\n    instance.context = context;\n  }\n\n  return instance;\n}\n\nclass ServerRenderer {\n  constructor(options) {\n    this.options = options;\n    this.previousWasTextNode = false;\n    setTargetPlatform('web');\n    setViewportWidth(options.viewportWidth);\n    setUnitPrecision(options.unitPrecision);\n  }\n\n  renderElementToString(element, context) {\n    if (typeof element === 'string') {\n      if (this.previousWasTextNode) {\n        return TEXT_SPLIT_COMMENT + escapeText(element);\n      }\n      this.previousWasTextNode = true;\n      return escapeText(element);\n    }\n\n    if (element == null || element === false || element === true) {\n      this.previousWasTextNode = false;\n      return '<!-- _ -->';\n    }\n\n    if (typeof element === 'number') {\n      if (this.previousWasTextNode) {\n        return TEXT_SPLIT_COMMENT + String(element);\n      }\n      this.previousWasTextNode = true;\n      return String(element);\n    }\n\n    if (Array.isArray(element)) {\n      let html = '';\n      for (var index = 0, length = element.length; index < length; index++) {\n        var child = element[index];\n        html = html + this.renderElementToString(child, context);\n      }\n      return html;\n    }\n\n    // pre compiled html\n    if (element.__html != null) { // __html may be empty string\n      let html = element.__html;\n\n      if (element.__isStartWithTextNode && this.previousWasTextNode) {\n        html = TEXT_SPLIT_COMMENT + html;\n      }\n\n      this.previousWasTextNode = element.__isEndWithTextNode ? true : false;\n      return html;\n    }\n\n    // pre compiled attrs\n    if (element.__attrs) {\n      return propsToString(element.__attrs, this.options);\n    }\n\n    const type = element.type;\n\n    if (type) {\n      const isClassComponent = type.prototype && type.prototype.render;\n      const isFunctionComponent = typeof type === 'function';\n\n      // class component || function component\n      if (isClassComponent || isFunctionComponent) {\n        const instance = createInstance(element, context);\n\n        const currentComponent = {\n          // For hooks to get current instance\n          _instance: instance\n        };\n\n        if (process.env.NODE_ENV !== 'production') {\n          const componetName = type.displayName || type.name || element;\n          // Give the component name in render error info (only for development)\n          currentComponent.__getName = () => componetName;\n        }\n\n        // Rax will use owner during rendering, eg: hooks, render error info.\n        shared.Host.owner = currentComponent;\n\n        if (process.env.NODE_ENV !== 'production') {\n          checkContext(type);\n        }\n\n        let currentContext = instance.context;\n        let childContext;\n\n        if (instance.getChildContext) {\n          childContext = instance.getChildContext();\n        } else if (instance._getChildContext) {\n          // Only defined in Provider\n          childContext = instance._getChildContext();\n        }\n\n        if (childContext) {\n          // Why not use Object.assign? for better performance\n          currentContext = merge({}, context, childContext);\n        }\n\n        const renderedElement = instance.render();\n\n        // Reset owner after render, or it will casue memory leak.\n        shared.Host.owner = null;\n\n        if (isClassComponent && instance.componentDidCatch) {\n          try {\n            return this.renderElementToString(renderedElement, currentContext);\n          } catch (e) {\n            instance.componentDidCatch(e);\n            return ERROR_COMMENT;\n          }\n        } else {\n          return this.renderElementToString(renderedElement, currentContext);\n        }\n      } else if (typeof type === 'string') {\n        // shoud set the identifier to false before render child\n        this.previousWasTextNode = false;\n\n        const props = element.props || EMPTY_OBJECT;\n        const isVoidElement = VOID_ELEMENTS[type];\n        let html = `<${type}${propsToString(props, this.options)}`;\n        let innerHTML;\n\n        if (props.dangerouslySetInnerHTML) {\n          innerHTML = props.dangerouslySetInnerHTML.__html;\n        }\n\n        if (isVoidElement) {\n          html = html + '>';\n        } else {\n          html = html + '>';\n          // When child is null or undefined, it should be render as <!-- _ -->\n          if (props.hasOwnProperty('children')) {\n            const children = props.children;\n            if (Array.isArray(children)) {\n              for (var i = 0, l = children.length; i < l; i++) {\n                var child = children[i];\n                html = html + this.renderElementToString(child, context);\n              }\n            } else {\n              html = html + this.renderElementToString(children, context);\n            }\n          } else if (innerHTML != null) { // When dangerouslySetInnerHTML is 0, it should be render as 0\n            html = html + innerHTML;\n          }\n\n          html = html + `</${type}>`;\n        }\n\n        this.previousWasTextNode = false;\n        return html;\n      } else {\n        throwInValidElementError(element);\n      }\n    } else {\n      throwInValidElementError(element);\n    }\n  }\n}\n\nfunction throwInValidElementError(element) {\n  let typeInfo = element === undefined ? '' :\n    '(found: ' + (isPlainObject(element) ? `object with keys {${Object.keys(element)}}` : element) + ')';\n\n  console.error(`Invalid element type, expected types: Element instance, string, boolean, array, null, undefined. ${typeInfo}`);\n}\n\nfunction isPlainObject(obj) {\n  return EMPTY_OBJECT.toString.call(obj) === '[object Object]';\n}\n\nexport function renderToString(element, options) {\n  const serverRenderer = new ServerRenderer(Object.assign({}, DEFAULT_STYLE_OPTIONS, options));\n  return serverRenderer.renderElementToString(element, {});\n}\n\nexport default {\n  renderToString\n};\n"
  },
  {
    "path": "packages/rax-set-native-props/README.md",
    "content": "# rax-set-native-props"
  },
  {
    "path": "packages/rax-set-native-props/package.json",
    "content": "{\n  \"name\": \"rax-set-native-props\",\n  \"version\": \"1.0.4\",\n  \"description\": \"Rax setNativeProps\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  },\n  \"dependencies\": {\n    \"universal-env\": \"^3.0.0\",\n    \"style-unit\": \"^3.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-set-native-props/src/flexbox.js",
    "content": "const BOX_ALIGN = {\n  stretch: 'stretch',\n  'flex-start': 'start',\n  'flex-end': 'end',\n  center: 'center'\n};\n\nconst BOX_ORIENT = {\n  row: 'horizontal',\n  column: 'vertical'\n};\n\nconst BOX_PACK = {\n  'flex-start': 'start',\n  'flex-end': 'end',\n  center: 'center',\n  'space-between': 'justify',\n  'space-around': 'justify' // Just same as `space-between`\n};\n\nconst FLEX_PROPS = {\n  display: true,\n  flex: true,\n  alignItems: true,\n  alignSelf: true,\n  flexDirection: true,\n  justifyContent: true,\n  flexWrap: true,\n};\n\nlet Flexbox = {\n  isFlexProp(prop) {\n    return FLEX_PROPS[prop];\n  },\n  display(value, style = {}) {\n    if (value === 'flex') {\n      style.display = ['-webkit-box', '-webkit-flex', 'flex'];\n    } else {\n      style.display = value;\n    }\n\n    return style;\n  },\n  flex(value, style = {}) {\n    style.webkitBoxFlex = value;\n    style.webkitFlex = value;\n    style.flex = value;\n    return style;\n  },\n  flexWrap(value, style = {}) {\n    style.webkitFlexWrap = value;\n    style.flexWrap = value;\n    return style;\n  },\n  alignItems(value, style = {}) {\n    style.webkitBoxAlign = BOX_ALIGN[value];\n    style.webkitAlignItems = value;\n    style.alignItems = value;\n    return style;\n  },\n  alignSelf(value, style = {}) {\n    style.webkitAlignSelf = value;\n    style.alignSelf = value;\n    return style;\n  },\n  flexDirection(value, style = {}) {\n    style.webkitBoxOrient = BOX_ORIENT[value];\n    style.webkitFlexDirection = value;\n    style.flexDirection = value;\n    return style;\n  },\n  justifyContent(value, style = {}) {\n    style.webkitBoxPack = BOX_PACK[value];\n    style.webkitJustifyContent = value;\n    style.justifyContent = value;\n    return style;\n  }\n};\n\nexport default Flexbox;"
  },
  {
    "path": "packages/rax-set-native-props/src/index.js",
    "content": "import { isWeex, isWeb } from 'universal-env';\nimport { convertUnit } from 'style-unit';\nimport { shared } from 'rax';\nimport flexbox from './flexbox';\n\nconst ADD_EVENT = 'addEvent';\nconst DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';\nconst CLASS_NAME = 'className';\nconst CLASS = 'class';\nconst STYLE = 'style';\nconst CHILDREN = 'children';\nconst EVENT_PREFIX_REGEXP = /^on[A-Z]/;\n\nconst objectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty;\n\nfunction hasOwnProperty(obj, key) {\n  return objectPrototypeHasOwnProperty.call(obj, key);\n}\n\nfunction setStyles(node, styles) {\n  if (isWeb) {\n    let tranformedStyles = {};\n    for (let prop in styles) {\n      let val = styles[prop];\n      if (flexbox.isFlexProp(prop)) {\n        flexbox[prop](val, tranformedStyles);\n      } else {\n        tranformedStyles[prop] = convertUnit(val, prop);\n      }\n    }\n    for (let prop in tranformedStyles) {\n      const transformValue = tranformedStyles[prop];\n      // hack handle compatibility issue\n      if (Array.isArray(transformValue)) {\n        for (let i = 0; i < transformValue.length; i++) {\n          node.style[prop] = transformValue[i];\n        }\n      } else {\n        node.style[prop] = transformValue;\n      }\n    }\n  } else if (isWeex) {\n    shared.Host.driver.setStyle(node, styles);\n  }\n}\n\nfunction addEventListener(node, eventName, eventHandler, props) {\n  if (isWeb) {\n    return node.addEventListener(eventName, eventHandler);\n  } else if (isWeex) {\n    return shared.Host.driver.addEventListener(node, eventName, eventHandler, props);\n  }\n}\n\nfunction setAttribute(node, propKey, propValue) {\n  if (isWeb) {\n    if (propKey === DANGEROUSLY_SET_INNER_HTML) {\n      return node.innerHTML = propValue.__html;\n    }\n    if (propKey === CLASS_NAME) {\n      propKey = CLASS;\n    }\n    if (propKey in node) {\n      try {\n        node[propKey] = propValue;\n      } catch (e) {\n        node.setAttribute(propKey, propValue);\n      }\n    } else {\n      node.setAttribute(propKey, propValue);\n    }\n  } else if (isWeex) {\n    shared.Host.driver.setAttribute(node, propKey, propValue);\n  }\n}\n\n/**\n * Set props directly to native node.\n * @param {Node} node Reference to node intance.\n * @param {Obejct} props k-v structure to props.\n */\nexport default function setNativeProps(node, props = {}) {\n  for (let prop in props) {\n    if (!hasOwnProperty(props, prop)) continue;\n\n    const value = props[prop];\n\n    // Skip children.\n    if (prop === CHILDREN) continue;\n\n    // Skip nullable value.\n    if (value === null || value === undefined) continue;\n\n    if (prop === STYLE) {\n      setStyles(node, value);\n    } else if (EVENT_PREFIX_REGEXP.test(prop)) {\n      const eventName = prop.slice(2).toLowerCase();\n      addEventListener(node, eventName, value, props);\n    } else {\n      setAttribute(node, prop, value);\n    }\n  }\n}"
  },
  {
    "path": "packages/rax-test-renderer/CHANGELOG.md",
    "content": "## CHANGELOG\n\n### 1.1.0\n\n- Refactor: avoid rax-test-renderer's dependence on `rax/lib/testing` which use `Class` or `Function` in rax inside\n"
  },
  {
    "path": "packages/rax-test-renderer/README.md",
    "content": "# rax-test-renderer [![npm](https://img.shields.io/npm/v/rax-test-renderer.svg)](https://www.npmjs.com/package/rax-test-renderer) [![Dependency Status](https://david-dm.org/alibaba/rax.svg?path=packages/rax-test-renderer)](https://david-dm.org/alibaba/rax.svg?path=packages/rax-test-renderer) [![Known Vulnerabilities](https://snyk.io/test/npm/rax-test-renderer/badge.svg)](https://snyk.io/test/npm/rax-test-renderer)\n\n> Rax renderer for snapshot testing.\n\n## Install\n\n```sh\n$ npm install --save-dev rax-test-renderer\n```\n\n## Usage\n\nThis package provides an renderer that can be used to render Rax components to pure JavaScript objects, without depending on the DOM or a native mobile environment:\n\n```jsx\nimport {createElement} from 'rax';\nimport renderer from 'rax-test-renderer';\n\nconst tree = renderer.create(\n  <Link page=\"https://example.com/\">Example</Link>\n);\n\nconsole.log(tree.toJSON());\n// { tagName: 'A',\n//   attributes: { href: 'https://example.com/' },\n//   children: [ 'Example' ] }\n```\n\nYou can also use Jest's snapshot testing feature to automatically save a copy of the JSON tree to a file and check in your tests that it hasn't changed: http://facebook.github.io/jest/blog/2016/07/27/jest-14.html.\n\n```jsx\nimport {createElement} from 'rax';\nimport renderer from 'rax-test-renderer';\n\ntest('Link renders correctly', () => {\n  const tree = renderer.create(\n    <Link page=\"https://example.com\">Example</Link>\n  ).toJSON();\n  expect(tree).toMatchSnapshot();\n});\n```\n"
  },
  {
    "path": "packages/rax-test-renderer/package.json",
    "content": "{\n  \"name\": \"rax-test-renderer\",\n  \"version\": \"1.1.0\",\n  \"description\": \"Rax renderer for snapshot testing.\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"module\": \"es/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"dependencies\": {\n    \"driver-server\": \"^1.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-test-renderer/src/__tests__/__snapshots__/snapshot.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`snapshot Link changes the class when hovered 1`] = `\nObject {\n  \"attributes\": Object {\n    \"class\": \"normal\",\n    \"href\": \"https://example.com\",\n  },\n  \"children\": Array [\n    \"Example\",\n  ],\n  \"eventListeners\": Object {\n    \"mouseenter\": [Function],\n    \"mouseleave\": [Function],\n  },\n  \"tagName\": \"A\",\n}\n`;\n\nexports[`snapshot Link changes the class when hovered 2`] = `\nObject {\n  \"attributes\": Object {\n    \"class\": \"hovered\",\n    \"href\": \"https://example.com\",\n  },\n  \"children\": Array [\n    \"Example\",\n  ],\n  \"eventListeners\": Object {\n    \"mouseenter\": [Function],\n    \"mouseleave\": [Function],\n  },\n  \"tagName\": \"A\",\n}\n`;\n\nexports[`snapshot Link changes the class when hovered 3`] = `\nObject {\n  \"attributes\": Object {\n    \"class\": \"normal\",\n    \"href\": \"https://example.com\",\n  },\n  \"children\": Array [\n    \"Example\",\n  ],\n  \"eventListeners\": Object {\n    \"mouseenter\": [Function],\n    \"mouseleave\": [Function],\n  },\n  \"tagName\": \"A\",\n}\n`;\n"
  },
  {
    "path": "packages/rax-test-renderer/src/__tests__/escapeText.js",
    "content": "import escapeText from '../escapeText';\n\ndescribe('escapeText', () => {\n  it('should escape boolean to string', function() {\n    expect(escapeText(true)).toBe('true');\n    expect(escapeText(false)).toBe('false');\n  });\n\n  it('should escape object to string', function() {\n    let escaped = escapeText({\n      toString: function() {\n        return 'ponys';\n      },\n    });\n\n    expect(escaped).toBe('ponys');\n  });\n\n  it('should escape number to string', function() {\n    expect(escapeText(42)).toBe('42');\n  });\n\n  it('should escape string', function() {\n    let escaped = escapeText('<script type=\\'\\' src=\"\"></script>');\n    expect(escaped).not.toContain('<');\n    expect(escaped).not.toContain('>');\n    expect(escaped).not.toContain('\\'');\n    expect(escaped).not.toContain('\\\"');\n\n    escaped = escapeText('&');\n    expect(escaped).toBe('&amp;');\n  });\n});\n"
  },
  {
    "path": "packages/rax-test-renderer/src/__tests__/renderer.js",
    "content": "/* eslint-disable react/no-did-mount-set-state */\n\nimport { createElement, Component } from 'rax';\nimport renderer from '../renderer';\n\ndescribe('renderer', () => {\n  beforeEach(function() {\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    jest.useRealTimers();\n  });\n\n  it('renders a simple component', () => {\n    function Link() {\n      return <a role=\"link\" />;\n    }\n\n    var component = renderer.create(<Link />);\n    expect(component.toJSON()).toEqual({\n      tagName: 'A',\n      attributes: { role: 'link' }\n    });\n  });\n\n  it('renders a component', () => {\n    class Link extends Component {\n      render() {\n        return (\n          <a\n            href={this.props.page || '#'}\n            onMouseEnter={this.props.onMouseEnter}\n            onMouseLeave={this.props.onMouseLeave}>\n            {this.props.children}\n          </a>\n        );\n      }\n    }\n\n    var noop = () => {};\n    var component = renderer.create(<Link onMouseEnter={noop} page=\"http://example.com\">Example</Link>);\n    expect(component.toJSON()).toEqual({\n      tagName: 'A',\n      attributes: {\n        href: 'http://example.com'\n      },\n      eventListeners: {\n        mouseenter: noop\n      },\n      children: ['Example'],\n    });\n  });\n\n  it('renders a top-level empty component', () => {\n    function Empty() {\n      return null;\n    }\n    var component = renderer.create(<Empty />);\n    expect(component.toJSON()).toEqual(null);\n  });\n\n  it('renders some basics with an update', () => {\n    var renders = 0;\n\n    class MyComponent extends Component {\n      state = {x: 3};\n\n      render() {\n        renders++;\n        return (\n          <div className=\"purple\">\n            {this.state.x}\n            <Child />\n            <Null />\n          </div>\n        );\n      }\n\n      componentDidMount() {\n        this.setState({x: 7});\n      }\n    }\n\n    var Child = () => {\n      renders++;\n      return <moo />;\n    };\n\n    var Null = () => {\n      renders++;\n      return null;\n    };\n\n    var component = renderer.create(<MyComponent />);\n    jest.runAllTimers();\n    expect(component.toJSON()).toEqual({\n      tagName: 'DIV',\n      attributes: { class: 'purple' },\n      children: [\n        '7',\n        {\n          tagName: 'MOO'\n        },\n      ],\n    });\n    expect(renders).toBe(6);\n  });\n\n  it('exposes the instance', () => {\n    class Mouse extends Component {\n      constructor() {\n        super();\n        this.state = {mouse: 'mouse'};\n      }\n      handleMoose() {\n        this.setState({mouse: 'moose'});\n      }\n      render() {\n        return <div>{this.state.mouse}</div>;\n      }\n    }\n    var component = renderer.create(<Mouse />);\n\n    expect(component.toJSON()).toEqual({\n      tagName: 'DIV',\n      children: ['mouse'],\n    });\n\n    var mouse = component.getInstance();\n    mouse.handleMoose();\n    jest.runAllTimers();\n\n    expect(component.toJSON()).toEqual({\n      tagName: 'DIV',\n      children: ['moose'],\n    });\n  });\n\n  it('updates types', () => {\n    var component = renderer.create(<div>mouse</div>);\n    expect(component.toJSON()).toEqual({\n      tagName: 'DIV',\n      children: ['mouse'],\n    });\n\n    component.update(<span>mice</span>);\n    expect(component.toJSON()).toEqual({\n      tagName: 'SPAN',\n      children: ['mice'],\n    });\n  });\n\n  it('does the full lifecycle', () => {\n    var log = [];\n    class Log extends Component {\n      render() {\n        log.push('render ' + this.props.name);\n        return <div />;\n      }\n      componentDidMount() {\n        log.push('mount ' + this.props.name);\n      }\n      componentWillUnmount() {\n        log.push('unmount ' + this.props.name);\n      }\n    }\n\n    var component = renderer.create(<Log key=\"foo\" name=\"Foo\" />);\n    component.update(<Log key=\"bar\" name=\"Bar\" />);\n    component.unmount();\n\n    expect(log).toEqual([\n      'render Foo',\n      'mount Foo',\n      'unmount Foo',\n      'render Bar',\n      'mount Bar',\n      'unmount Bar',\n    ]);\n  });\n\n  it('supports unmounting when using refs', () => {\n    class Foo extends Component {\n      render() {\n        return <div ref=\"foo\" />;\n      }\n    }\n    const inst = renderer.create(\n      <Foo />,\n      {createNodeMock: () => 'foo'}\n    );\n    expect(() => inst.unmount()).not.toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/rax-test-renderer/src/__tests__/snapshot.js",
    "content": "import { createElement, Component } from 'rax';\nimport renderer from '../renderer';\n\nconst STATUS = {\n  NORMAL: 'normal',\n  HOVERED: 'hovered',\n};\n\nclass Link extends Component {\n  constructor() {\n    super();\n\n    this._onMouseEnter = this._onMouseEnter.bind(this);\n    this._onMouseLeave = this._onMouseLeave.bind(this);\n\n    this.state = {\n      class: STATUS.NORMAL,\n    };\n  }\n\n  _onMouseEnter() {\n    this.setState({class: STATUS.HOVERED});\n  }\n\n  _onMouseLeave() {\n    this.setState({class: STATUS.NORMAL});\n  }\n\n  render() {\n    return (\n      <a\n        className={this.state.class}\n        href={this.props.page || '#'}\n        onMouseEnter={this._onMouseEnter}\n        onMouseLeave={this._onMouseLeave}>\n        {this.props.children}\n      </a>\n    );\n  }\n}\n\ndescribe('snapshot', () => {\n  beforeEach(function() {\n    jest.useFakeTimers();\n  });\n\n  afterEach(function() {\n    jest.useRealTimers();\n  });\n\n  test('Link changes the class when hovered', () => {\n    const component = renderer.create(\n      <Link page=\"https://example.com\">Example</Link>\n    );\n    let tree = component.toJSON();\n    expect(tree).toMatchSnapshot();\n\n    // manually trigger the callback\n    tree.eventListeners.mouseenter();\n    jest.runAllTimers();\n    // re-rendering\n    tree = component.toJSON();\n    expect(tree).toMatchSnapshot();\n\n    // manually trigger the callback\n    tree.eventListeners.mouseleave();\n    jest.runAllTimers();\n    // re-rendering\n    tree = component.toJSON();\n    expect(tree).toMatchSnapshot();\n  });\n});\n\n"
  },
  {
    "path": "packages/rax-test-renderer/src/__tests__/styleToCSS.js",
    "content": "import styleToCSS from '../styleToCSS';\n\ndescribe('StyleToCSS', () => {\n  it('convert unitless style to css', () => {\n    let css = styleToCSS({\n      background: 'black'\n    });\n\n    expect(css).toBe('background:black;');\n  });\n\n  it('convert rem unit style to css', () => {\n    let css = styleToCSS({\n      width: '750rem'\n    });\n\n    expect(css).toBe('width:750rem;');\n\n    let css2 = styleToCSS({\n      width: 750\n    });\n    expect(css2).toBe('width:750rem;');\n\n    let css3 = styleToCSS({\n      width: '750px'\n    });\n    expect(css3).toBe('width:750px;');\n  });\n\n  it('convert vendor prefix style to css', () => {\n    let css = styleToCSS({\n      WebkitBorder: 1\n    });\n    expect(css).toBe('-webkit-border:1rem;');\n  });\n});\n"
  },
  {
    "path": "packages/rax-test-renderer/src/escapeText.js",
    "content": "const ESCAPE_LOOKUP = {\n  '&': '&amp;',\n  '>': '&gt;',\n  '<': '&lt;',\n  '\"': '&quot;',\n  '\\'': '&#x27;',\n};\n\nconst ESCAPE_REGEX = /[&><\"']/g;\n\nfunction escaper(match) {\n  return ESCAPE_LOOKUP[match];\n}\n\nexport default function escapeText(text) {\n  return String(text).replace(ESCAPE_REGEX, escaper);\n}\n"
  },
  {
    "path": "packages/rax-test-renderer/src/index.js",
    "content": "import renderer from './renderer';\n\nmodule.exports = renderer;\n"
  },
  {
    "path": "packages/rax-test-renderer/src/renderer.js",
    "content": "import { shared } from 'rax';\nimport ServerDriver from 'driver-server';\nimport Serializer from './serializer';\n\nconst { Instance, Host } = shared;\n\n// For inject Host init options\nHost.driver = ServerDriver;\n\nexport default {\n  create(element) {\n    let container = ServerDriver.createBody();\n    let rootInstance = Instance.mount(element, container, {});\n    // The field corresponding to node and instance is _r, which you can see in rax/src/vdom/instance\n    let renderedComponent = rootInstance.__getRenderedComponent();\n\n    renderedComponent.toJSON = () => {\n      return new Serializer(container).toJSON();\n    };\n\n    renderedComponent.getInstance = () => {\n      return renderedComponent._instance;\n    };\n\n    renderedComponent.update = (element) => {\n      Instance.mount(element, container, {});\n    };\n\n    renderedComponent.unmount = () => {\n      let component = Instance.get(container);\n\n      if (!component) {\n        return false;\n      }\n\n      Instance.remove(container);\n      component._internal.unmountComponent();\n\n      return true;\n    };\n\n    return renderedComponent;\n  }\n};\n"
  },
  {
    "path": "packages/rax-test-renderer/src/serializer.js",
    "content": "import escapeText from './escapeText';\nimport styleToCSS from './styleToCSS';\n\nconst ELEMENT_NODE = 1;\nconst TEXT_NODE = 3;\nconst COMMENT_NODE = 8;\n\n// For HTML, certain tags should omit their close tag. We keep a whitelist for\n// those special-case tags.\nconst OMITTED_CLOSE_TAGS = {\n  'area': true,\n  'base': true,\n  'br': true,\n  'col': true,\n  'embed': true,\n  'hr': true,\n  'img': true,\n  'input': true,\n  'keygen': true,\n  'link': true,\n  'meta': true,\n  'param': true,\n  'source': true,\n  'track': true,\n  'wbr': true,\n};\n\n/**\n * Escapes attribute value to prevent scripting attacks.\n *\n * @param {*} value Value to escape.\n * @return {string} An escaped string.\n */\nfunction quoteAttribute(prop, value) {\n  return `${prop}=\"${escapeText(value)}\"`;\n}\n\nfunction createOpenTagMarkup(tagName, style, attributes) {\n  let tagOpen = `<${tagName}`;\n\n  if (style) {\n    let styleAttr = styleToCSS(style);\n    if (styleAttr) {\n      tagOpen += ' ' + quoteAttribute('style', styleAttr);\n    }\n  }\n\n  if (attributes) {\n    for (let attrKey in attributes) {\n      tagOpen += ' ' + quoteAttribute(attrKey, attributes[attrKey]);\n    }\n  }\n\n  return tagOpen;\n}\n\nclass Serializer {\n  constructor(node) {\n    this.html = '';\n    this.startNode = node;\n  }\n\n  toJSON() {\n    return this.toJSONChildren(this.startNode, true);\n  }\n\n  toJSONChildren(parentNode, isTopLevel) {\n    let childNodes = parentNode.childNodes;\n\n    if (childNodes) {\n      let children = [];\n\n      for (let i = 0, len = childNodes.length; i < len; i++) {\n        let node = childNodes[i];\n        if (node.nodeType === ELEMENT_NODE) {\n          let json = {\n            tagName: node.tagName,\n          };\n\n          let childrenJSON = this.toJSONChildren(node);\n          if (childrenJSON) {\n            json.children = childrenJSON;\n          }\n\n          if (Object.keys(node.style).length > 0) {\n            json.style = node.style;\n          }\n\n          if (Object.keys(node.attributes).length > 0) {\n            json.attributes = node.attributes;\n          }\n\n          if (Object.keys(node.eventListeners).length > 0) {\n            json.eventListeners = node.eventListeners;\n          }\n\n          children.push(json);\n        } else if (node.nodeType === TEXT_NODE) {\n          var text = node.data;\n          if (typeof text === 'string') {\n            text = escapeText(text);\n          }\n          children.push(text);\n        }\n      }\n\n      // Do not wrap array when only child in top-level\n      if (isTopLevel && children.length === 1) {\n        return children[0];\n      }\n\n      return children.length === 0 ? null : children;\n    }\n\n    return null;\n  }\n\n  serialize() {\n    this.serializeChildren(this.startNode);\n    return this.html;\n  }\n\n  serializeChildren(parentNode) {\n    let childNodes = parentNode.childNodes;\n\n    if (childNodes) {\n      for (let i = 0, len = childNodes.length; i < len; i++) {\n        let node = childNodes[i];\n        if (node.nodeType === ELEMENT_NODE) {\n          let tagName = node.tagName.toLowerCase();\n\n          this.html += createOpenTagMarkup(tagName, node.style, node.attributes);\n\n          if (OMITTED_CLOSE_TAGS[tagName]) {\n            this.html += '/>';\n          } else {\n            this.html += '>';\n            if (node.__html) {\n              this.html += node.__html;\n            } else {\n              this.serializeChildren(node);\n            }\n            this.html += `</${tagName}>`;\n          }\n        } else if (node.nodeType === TEXT_NODE) {\n          this.html += escapeText(node.data);\n        } else if (node.nodeType === COMMENT_NODE) {\n          this.html += '<!--' + node.data + '-->';\n        }\n      }\n    }\n  }\n}\n\nexport default Serializer;\n"
  },
  {
    "path": "packages/rax-test-renderer/src/styleToCSS.js",
    "content": "// TODO process flexbox polyfill\nexport default function styleToCSS(style) {\n  let css = '';\n  for (let prop in style) {\n    if (style.hasOwnProperty(prop)) {\n      let val = style[prop];\n      if (val != null) {\n        let unit = '';\n        if (typeof val === 'number' || String(parseFloat(val)).length === val.length) unit = 'rem';\n        css += `${prop.replace(/([A-Z])/g, '-$1').toLowerCase()}:${val}${unit};`;\n      }\n    }\n  }\n  return css;\n}\n"
  },
  {
    "path": "packages/rax-unmount-component-at-node/README.md",
    "content": "# rax-unmount-component-at-node"
  },
  {
    "path": "packages/rax-unmount-component-at-node/package.json",
    "content": "{\n  \"name\": \"rax-unmount-component-at-node\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Rax unmountComponentAtNode\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"engines\": {\n    \"npm\": \">=3.0.0\"\n  },\n  \"peerDependencies\": {\n    \"rax\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/rax-unmount-component-at-node/src/__tests__/unmountComponentAtNode.js",
    "content": "/* @jsx createElement */\n\nimport { createElement, render, shared } from 'rax';\nimport unmountComponentAtNode from '../';\n\nconst { Host } = shared;\n\ndescribe('unmountComponentAtNode', () => {\n  beforeEach(() => {\n    Host.driver = null;\n  });\n\n  afterEach(() => {\n    Host.driver = null;\n  });\n\n  it('unmout component', () => {\n    let appendChildMock = jest.fn();\n    let removeChildMock = jest.fn();\n    let body = {tagName: 'BODY'};\n\n    Host.driver = {\n      createElement() {\n        return {tagName: 'DIV'};\n      },\n      appendChild: appendChildMock,\n      removeChild: removeChildMock,\n      removeAllEventListeners() {}\n    };\n\n    render(<div />, body);\n    unmountComponentAtNode(body);\n\n    let call = appendChildMock.mock.calls[0];\n    expect(call[0].tagName).toBe('DIV');\n    expect(call[1].tagName).toBe('BODY');\n\n    let call2 = removeChildMock.mock.calls[0];\n    expect(call2[0].tagName).toBe('DIV');\n    expect(call2[1].tagName).toBe('BODY');\n  });\n});\n"
  },
  {
    "path": "packages/rax-unmount-component-at-node/src/index.js",
    "content": "import { shared } from 'rax';\n\nconst { Instance } = shared;\n\nexport default function unmountComponentAtNode(node) {\n  let component = Instance.get(node);\n\n  if (!component) {\n    return false;\n  }\n\n  Instance.remove(node);\n  component._internal.unmountComponent();\n\n  return true;\n};\n"
  },
  {
    "path": "packages/style-unit/CHANGELOG.md",
    "content": "## Changelog\n\n## v3.0.5\n\n- Fix: fix transform rpx error in node env.\n\n## v3.0.4\n\n- Fix: add esmodule result\n\n## v3.0.3\n\n- Chore: add `@babel/runtime` as dependency\n\n### v3.0.2\n\n- Bump version\n\n### v3.0.1\n\n- Refactor: avoid pollute `global` variable\n- Fix: converted property cache key is invalid\n- Fix: will not replace `rpx` to `vw` when value contains `rpx`\n"
  },
  {
    "path": "packages/style-unit/README.md",
    "content": "# style-unit\n\n> Unit conversion for calculating dimensional css attributes, especially for rpx.\n\n## API\n\nconvertUnit(value, prop, platform);\n\n| Property | Type          | Required | Description                                                  |\n| -------- | ------------- | -------- | ------------------------------------------------------------ |\n| value    | string/number | true     |                                                              |\n| prop     | string        | true     |                                                              |\n| platform | string        | false    | Auto assignment with [universal-env](https://www.npmjs.com/package/universal-env), different platforms have different rpx conversion. Details are as follows. |\n\n## Web \n\nIn Web, Calculate rpx to vw (relative to viewport width 750). \n\n750rpx -> 100vw\n\n### setViewportWidth\n\nYou can use `setViewportWidth` method update viewport width\n\nsetViewportWidth(1500);\n\n750rpx -> 50vw\n\n\n## Weex \n\nIn Weex, Calculate rpx to px (viewport width is 750). \n\n750rpx -> 750px\n\n### setRpx\n\nYou can use `setRpx` method update coefficient of 750\n\nsetRpx(1500 / 750)\n\n750rpx -> 1500px\n\n## MiniApp\n\nrpx (responsive pixel): Adaptable to the screen width in MiniApp. The specified screen width is 750 rpx. If the screen width on iPhone6 is 375 px (750 physical pixels), then 750 rpx = 375 px = 750 physical pixels, i.e. 1 rpx = 0.5 px = 1 physical pixel.\n\n## Node.js\n\nUse Weex result:\n```\nconvertUnit('500rpx', 'width', 'weex')\n```\nUse Web result:\n```\nconvertUnit('500rpx', 'width', 'web')\n```"
  },
  {
    "path": "packages/style-unit/package.json",
    "content": "{\n  \"name\": \"style-unit\",\n  \"version\": \"3.0.5\",\n  \"description\": \"style-unit\",\n  \"license\": \"BSD-3-Clause\",\n  \"main\": \"lib/index.js\",\n  \"module\": \"es/index.js\",\n  \"files\": [\n    \"lib\",\n    \"es\",\n    \"!__tests__\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/alibaba/rax.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/alibaba/rax/issues\"\n  },\n  \"homepage\": \"https://github.com/alibaba/rax#readme\",\n  \"dependencies\": {\n    \"universal-env\": \"^3.0.0\",\n    \"@babel/runtime\": \"^7.14.6\"\n  }\n}\n"
  },
  {
    "path": "packages/style-unit/src/__tests__/style-unit.miniApp.js",
    "content": "import { convertUnit } from '..';\n\njest.mock('universal-env', () => {\n  return {\n    isMiniApp: true,\n    isWeb: false,\n    isWeex: false\n  };\n});\n\ndescribe('Mini-App style-unit', () => {\n  describe('convertUnit', () => {\n    it('should not recognize number', () => {\n      expect(convertUnit(500, 'width')).toEqual(500);\n    });\n\n    it('should recognize number string', () => {\n      expect(convertUnit('500', 'width')).toEqual('500');\n    });\n\n    it('should recognize px', () => {\n      expect(convertUnit('276px', 'width')).toEqual('276px');\n    });\n\n    it('should recognize rem', () => {\n      expect(convertUnit('500rem', 'width')).toEqual('500rem');\n    });\n\n    it('should recognize rpx', () => {\n      expect(convertUnit('375rpx', 'width')).toEqual('375rpx');\n    });\n\n    it('should recognize vh', () => {\n      expect(convertUnit('500vh', 'width')).toEqual('500vh');\n    });\n\n    it('should recognize 0', () => {\n      expect(convertUnit('0', 'width')).toEqual('0');\n      expect(convertUnit(0, 'width')).toEqual(0);\n    });\n\n    it('should recognize transform', () => {\n      expect(convertUnit('375rpx 20px 375rpx', 'margin')).toEqual('375rpx 20px 375rpx');\n      expect(convertUnit('translateX(375rpx) translateY(375rpx)', 'transform')).toEqual('translateX(375rpx) translateY(375rpx)');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/style-unit/src/__tests__/style-unit.web.js",
    "content": "import { convertUnit, getViewportWidth, setViewportWidth } from '..';\n\njest.mock('universal-env', () => {\n  return {\n    isMiniApp: false,\n    isWeb: true,\n    isWeex: false\n  };\n});\n\ndescribe('Web style-unit', () => {\n  describe('convertUnit', () => {\n    setViewportWidth(375);\n    it('should not recognize number', () => {\n      expect(convertUnit(500, 'width')).toEqual(500);\n    });\n\n    it('should recognize number string', () => {\n      expect(convertUnit('500', 'width')).toEqual('500');\n    });\n\n    it('should recognize px', () => {\n      expect(convertUnit('276px', 'width')).toEqual('276px');\n    });\n\n    it('should recognize rem', () => {\n      expect(convertUnit('500rem', 'width')).toEqual('500rem');\n    });\n\n    it('should recognize rpx', () => {\n      expect(convertUnit('375rpx', 'width')).toEqual('100vw');\n    });\n\n    it('should not transform rpx to vw with url()', () => {\n      expect(convertUnit('url(\"abc2rpx\")', 'background-image')).toEqual('url(\"abc2rpx\")');\n    });\n\n    it('should recognize vh', () => {\n      expect(convertUnit('500vh', 'width')).toEqual('500vh');\n    });\n\n    it('should recognize 0', () => {\n      expect(convertUnit('0', 'width')).toEqual('0');\n      expect(convertUnit(0, 'width')).toEqual(0);\n    });\n\n    it('should recognize transform', () => {\n      expect(convertUnit('375rpx 20px 375rpx', 'margin')).toEqual('100vw 20px 100vw');\n      expect(convertUnit('translateX(375rpx) translateY(375rpx)', 'transform')).toEqual('translateX(100vw) translateY(100vw)');\n    });\n  });\n\n  describe('exported API', () => {\n    it('get and set viewportWidth', () => {\n      setViewportWidth(500);\n      expect(getViewportWidth()).toEqual(500);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/style-unit/src/__tests__/style-unit.weex.js",
    "content": "import { convertUnit, setDecimalPixelTransformer, getRpx, setRpx } from '..';\n\njest.mock('universal-env', () => {\n  return {\n    isMiniApp: false,\n    isWeb: false,\n    isWeex: true\n  };\n});\n\ndescribe('Weex style-unit', () => {\n  describe('convertUnit', () => {\n    setRpx(414 / 750);\n\n    it('should recognize number', () => {\n      expect(convertUnit(500, 'width')).toEqual(500);\n    });\n\n    it('should recognize number string', () => {\n      expect(convertUnit('500', 'width')).toEqual('500');\n    });\n\n    it('should recognize px', () => {\n      expect(convertUnit('276px', 'width')).toEqual('276px');\n    });\n\n    it('should recognize rem', () => {\n      expect(convertUnit('500rem', 'width')).toEqual('500rem');\n    });\n\n    it('should recognize rpx', () => {\n      expect(convertUnit('500rpx', 'width')).toEqual('276px');\n    });\n\n    it('should recognize vh', () => {\n      expect(convertUnit('500vh', 'width')).toEqual('500vh');\n    });\n\n    it('should recognize 0', () => {\n      expect(convertUnit('0', 'width')).toEqual('0');\n      expect(convertUnit(0, 'width')).toEqual(0);\n    });\n\n    it('should ignore unitless prop', () => {\n      expect(convertUnit(1, 'flex')).toEqual(1);\n    });\n\n    it('should recognize transform', () => {\n      expect(convertUnit('500rpx 20px 500rpx', 'margin')).toEqual('276px 20px 276px');\n      expect(convertUnit('translateX(500rpx) translateY(500rpx)', 'transform')).toEqual('translateX(276px) translateY(276px)');\n    });\n  });\n\n  describe('exported API', () => {\n    it('setDecimalPixelTransformer', () => {\n      setDecimalPixelTransformer((val) => val);\n      expect(convertUnit('1500rpx', 'width')).toEqual('1500rpx');\n    });\n\n    it('get and set rpx', () => {\n      setRpx(500);\n      expect(getRpx()).toEqual(500);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/style-unit/src/index.js",
    "content": "import { isWeb, isWeex, isNode } from 'universal-env';\n\nconst RPX_REG = /\"[^\"]+\"|'[^']+'|url\\([^\\)]+\\)|(\\d*\\.?\\d+)rpx/g;\nlet __rpx_coefficient__;\nlet __viewport_width__;\n\n// convertUnit method targetPlatform\nlet targetPlatform = isWeb ? 'web' : isWeex ? 'weex' : isNode ? 'node' : '';\n\n// Init toFixed method\nlet unitPrecision = 4;\n\nconst toFixed = (number, precision) => {\n  const multiplier = Math.pow(10, precision + 1);\n  const wholeNumber = Math.floor(number * multiplier);\n  return Math.round(wholeNumber / 10) * 10 / multiplier;\n};\n\n// Dedault decimal px transformer.\nlet decimalPixelTransformer = (rpx, $1) => $1 ? parseFloat(rpx) * getRpx() + 'px' : rpx;\n\n// Default decimal vw transformer.\nconst decimalVWTransformer = (rpx, $1) => $1 ? toFixed(parseFloat(rpx) / (getViewportWidth() / 100), unitPrecision) + 'vw' : rpx;\n\n// Default 1 rpx to 1 px\nif (getRpx() === undefined) {\n  setRpx(1);\n}\n\n// Viewport width, default to 750.\nif (getViewportWidth() === undefined) {\n  setViewportWidth(750);\n}\n\nclass CustomMap {\n  __store = {}\n  set(key, value) {\n    this.__store[`${key}_${typeof key}`] = value;\n  }\n  get(key) {\n    return this.__store[`${key}_${typeof key}`];\n  }\n  has(key) {\n    return Object.prototype.hasOwnProperty.call(this.__store, `${key}_${typeof key}`);\n  }\n}\n\n/**\n * Is string contains rpx\n * note: rpx is an alias to rpx\n * @param {String} str\n * @returns {Boolean}\n */\nexport function isRpx(str) {\n  return typeof str === 'string' && RPX_REG.test(str);\n}\n\n/**\n * Calculate rpx\n * @param {String} str\n * @returns {String}\n */\nexport function calcRpx(str) {\n  if (targetPlatform === 'web' || targetPlatform === 'node') {\n    // In Web convert rpx to 'vw', same as driver-dom and driver-universal.\n    // In Node is same as web for SSR.\n    // '375rpx' => '50vw'\n    return str.replace(RPX_REG, decimalVWTransformer);\n  } else if (targetPlatform === 'weex') {\n    // In Weex convert rpx to 'px'.\n    // '375rpx' => 375 * px\n    return str.replace(RPX_REG, decimalPixelTransformer);\n  } else {\n    // Other platform return original value, like Mini-App and WX Mini-Program ...\n    // '375rpx' => '375rpx'\n    return str;\n  }\n}\n\nexport function getRpx() {\n  return __rpx_coefficient__;\n}\n\nexport function setRpx(rpx) {\n  __rpx_coefficient__ = rpx;\n}\n\nexport function getViewportWidth() {\n  return __viewport_width__;\n}\n\nexport function setViewportWidth(viewport) {\n  __viewport_width__ = viewport;\n}\n\n/**\n * Set a function to transform unit of pixel,\n * default to passthrough.\n * @param {Function} transformer function\n */\nexport function setDecimalPixelTransformer(transformer) {\n  decimalPixelTransformer = transformer;\n}\n\n/**\n * Set unit precision.\n * @param n {Number} Unit precision, default to 4.\n */\nexport function setUnitPrecision(n) {\n  unitPrecision = n;\n}\n\n/**\n * Create a cached version of a pure function.\n * Use the first params as cache key.\n */\nexport function cached(fn) {\n  const cache = new CustomMap();\n  return function cachedFn(...args) {\n    const key = args[0];\n    if (!cache.has(key)) cache.set(key, fn(...args));\n    return cache.get(key);\n  };\n}\n\nexport function setTargetPlatform(platform) {\n  targetPlatform = platform;\n}\n\n/**\n * Convert rpx.\n * @param value\n * @param prop\n * @param platform\n * @return {String} Transformed value.\n */\nexport const convertUnit = cached((value, prop, platform) => {\n  if (platform) {\n    setTargetPlatform(platform);\n  }\n  return isRpx(value) ? calcRpx(value) : value;\n});\n"
  },
  {
    "path": "scripts/add-owner.js",
    "content": "// Usage: node scripts/add-owner.js user\n'use strict';\n\nconst path = require('path');\nconst fs = require('fs');\nconst execSync = require('child_process').execSync;\n\nconst PACKAGES_DIR = path.resolve(__dirname, '../packages');\n\nconst user = process.argv[2];\n\nfs.readdirSync(PACKAGES_DIR)\n  .forEach(function(packageName) {\n    const pkgJSON = path.join(PACKAGES_DIR, packageName, 'package.json');\n    if (!fs.existsSync(pkgJSON)) {\n      return;\n    }\n\n    var packageJSON = require(pkgJSON);\n    if (packageJSON.private) {\n      return console.log('Skip private package:', packageName);\n    }\n\n    const cmd = 'npm owner add ' + user + ' ' + packageName;\n    console.log(cmd);\n    execSync(\n      cmd,\n      {\n        stdio: 'inherit'\n      }\n    );\n  });\n"
  },
  {
    "path": "scripts/bench/.gitignore",
    "content": "node_modules\ndist\nprefs\nerrors\nresults\n\nframeworks/*/package-lock.json"
  },
  {
    "path": "scripts/bench/README.md",
    "content": "# Rax Benchmarking\n\nThis work is derived from [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark).\n\n\n```bash\n# build and run all benchmarks\nnpm start\n\n# only run `rax-local` , and compare data in the `results` fold (to improve bench times)\nnpm start -- --local\n\n# run specific frameworks and benchmarks with prefixes like in the following example\nnpm start -- --framework rax preact --benchmark 01_ 02_\n\n# skip build\nnpm start -- --skip-build\n\n# build a single framework\ncd frameworks/rax\nnpm install\nnpm run build-prod\n```\n\n"
  },
  {
    "path": "scripts/bench/chromePreferences.json",
    "content": "{\n  \"translate\": {\n    \"enabled\": false\n  }\n}\n"
  },
  {
    "path": "scripts/bench/css/bootstrap.css",
    "content": "* {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n.jumbotron {\n  padding-top: 30px;\n  padding-bottom: 30px;\n  margin-bottom: 30px;\n  color: inherit;\n  background-color: #eee;\n}\n\n.container {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n@media screen and (min-width: 768px){\n  .container .jumbotron, .container-fluid .jumbotron {\n    padding-right: 60px;\n    padding-left: 60px;\n  }\n}\n@media (min-width: 768px) {\n  .container {\n    width: 750px;\n  }\n}\n@media (min-width: 992px) {\n  .container {\n    width: 970px;\n  }\n}\n@media (min-width: 1200px) {\n  .container {\n    width: 1170px;\n  }\n}\n\n.row {\n  margin-right: -15px;\n  margin-left: -15px;\n  display: table;\n}\n\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n  position: relative;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n  float: left;\n}\n.col-xs-6 {\n  width: 50%;\n}\n.col-xs-5 {\n  width: 41.66666667%;\n}\n.col-xs-4 {\n  width: 33.33333333%;\n}\n.col-xs-3 {\n  width: 25%;\n}\n.col-xs-2 {\n  width: 16.66666667%;\n}\n.col-xs-1 {\n  width: 8.33333333%;\n}\n@media (min-width: 768px) {\n  .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n    float: left;\n  }\n  .col-sm-6 {\n    width: 50%;\n  }\n  .col-sm-5 {\n    width: 41.66666667%;\n  }\n  .col-sm-4 {\n    width: 33.33333333%;\n  }\n  .col-sm-3 {\n    width: 25%;\n  }\n  .col-sm-2 {\n    width: 16.66666667%;\n  }\n  .col-sm-1 {\n    width: 8.33333333%;\n  }\n}\n@media (min-width: 992px) {\n  .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n    float: left;\n  }\n  .col-md-6 {\n    width: 50%;\n  }\n  .col-md-5 {\n    width: 41.66666667%;\n  }\n  .col-md-4 {\n    width: 33.33333333%;\n  }\n  .col-md-3 {\n    width: 25%;\n  }\n  .col-md-2 {\n    width: 16.66666667%;\n  }\n  .col-md-1 {\n    width: 8.33333333%;\n  }\n}\n@media (min-width: 1200px) {\n  .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n    float: left;\n  }\n  .col-lg-6 {\n    width: 50%;\n  }\n  .col-lg-5 {\n    width: 41.66666667%;\n  }\n  .col-lg-4 {\n    width: 33.33333333%;\n  }\n  .col-lg-3 {\n    width: 25%;\n  }\n  .col-lg-2 {\n    width: 16.66666667%;\n  }\n  .col-lg-1 {\n    width: 8.33333333%;\n  }\n}\n\n.btn-primary {\n  color: #fff;\n  background-color: #337ab7;\n  border-color: #2e6da4;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n}\n\n.btn {\n  display: inline-block;\n  padding: 6px 12px;\n  margin-bottom: 0;\n  font-size: 14px;\n  font-weight: 400;\n  line-height: 1.42857143;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  -ms-touch-action: manipulation;\n  touch-action: manipulation;\n  cursor: pointer;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n\n.table {\n  width: 100%;\n  max-width: 100%;\n  margin-bottom: 20px;\n}\n\n.table-hover>tbody>tr:hover {\n  background-color: #f5f5f5;\n}\n\n.table-striped>tbody>tr:nth-of-type(odd) {\n  background-color: #f9f9f9;\n}\n\n.table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td, .table>thead>tr>th {\n  padding: 8px;\n  line-height: 1.42857143;\n  vertical-align: top;\n  border-top: 1px solid #ddd;\n}\n"
  },
  {
    "path": "scripts/bench/css/currentStyle.css",
    "content": "@import url(\"/css/bootstrap.css\");\n@import url(\"/css/main.css\");\n"
  },
  {
    "path": "scripts/bench/css/main.css",
    "content": "body {\n  padding: 10px 0 0 0;\n  margin: 0;\n  overflow-y: scroll;\n}\n\n#duration {\n  padding-top: 0px;\n}\n\n.jumbotron {\n  padding-top:10px;\n  padding-bottom:10px;\n}\n\n.test-data a {\n  display: block;\n}\n.preloadicon {\n  position: absolute;\n  top:-20px;\n  left:-20px;\n}\n.col-sm-6.smallpad {\n  padding: 5px;\n}\n.jumbotron .row h1 {\n  font-size: 40px;\n}\n\na {\n  color: #337ab7;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n"
  },
  {
    "path": "scripts/bench/frameworks/preact/.babelrc",
    "content": "{\n  \"presets\": [\n    [\n      \"@babel/preset-env\",\n      {\n        \"targets\": {\n          \"browsers\": [\"last 1 chrome versions\"]\n        },\n        \"loose\": true\n      }\n    ],\n    \"@babel/preset-react\"\n  ],\n  \"plugins\": []\n}\n"
  },
  {
    "path": "scripts/bench/frameworks/preact/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>preact</title>\n  <link href=\"/css/currentStyle.css\" rel=\"stylesheet\"/>\n</head>\n<body>\n  <div id='main'></div>\n  <script src='dist/main.js'></script>\n</body>\n</html>\n"
  },
  {
    "path": "scripts/bench/frameworks/preact/package.json",
    "content": "{\n  \"name\": \"js-framework-benchmark-preact\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Benchmark for preact\",\n  \"scripts\": {\n    \"build-dev\": \"webpack -w -d\",\n    \"build-prod\": \"webpack\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.4.3\",\n    \"@babel/preset-env\": \"^7.4.3\",\n    \"@babel/preset-react\": \"^7.0.0\",\n    \"babel-loader\": \"^8.0.5\",\n    \"webpack\": \"4.22.0\",\n    \"webpack-cli\": \"3.1.2\"\n  },\n  \"dependencies\": {\n    \"preact\": \"^8.2.6\"\n  }\n}\n"
  },
  {
    "path": "scripts/bench/frameworks/preact/src/Main.jsx",
    "content": "'use strict';\n/** @jsx preact.h */\n\nvar preact = require('preact');\n\nvar { render, h, Component } = preact;\nconst {Row} = require('./Row');\nconst {Store} = require('./Store');\n\nvar startTime;\nvar lastMeasure;\nvar startMeasure = function(name) {\n  // console.timeStamp(name);\n  startTime = performance.now();\n  lastMeasure = name;\n};\nvar stopMeasure = function() {\n  var last = lastMeasure;\n  if (lastMeasure) {\n    window.setTimeout(function() {\n      lastMeasure = null;\n      var stop = performance.now();\n      var duration = 0;\n      console.log(last + ' took ' + (stop - startTime));\n    }, 0);\n  }\n};\n\nexport class Main extends Component {\n  constructor(props) {\n    super(props);\n    this.state = {store: new Store()};\n    this.select = this.select.bind(this);\n    this.delete = this.delete.bind(this);\n    this.add = this.add.bind(this);\n    this.run = this.run.bind(this);\n    this.update = this.update.bind(this);\n    this.runLots = this.runLots.bind(this);\n    this.clear = this.clear.bind(this);\n    this.swapRows = this.swapRows.bind(this);\n    this.start = 0;\n    this.length = 0;\n\n    window.app = this;\n  }\n  printDuration() {\n    stopMeasure();\n  }\n  componentDidUpdate() {\n    this.printDuration();\n  }\n  componentDidMount() {\n    this.printDuration();\n  }\n  run() {\n    startMeasure('run');\n    this.state.store.run();\n    this.setState({store: this.state.store});\n  }\n  add() {\n    startMeasure('add');\n    this.state.store.add();\n    this.setState({store: this.state.store});\n  }\n  update() {\n    startMeasure('update');\n    this.state.store.update();\n    this.setState({store: this.state.store});\n  }\n  select(id) {\n    startMeasure('select');\n    this.state.store.select(id);\n    this.setState({store: this.state.store});\n  }\n  delete(id) {\n    startMeasure('delete');\n    this.state.store.delete(id);\n    this.setState({store: this.state.store});\n  }\n  runLots() {\n    startMeasure('runLots');\n    this.state.store.runLots();\n    this.setState({store: this.state.store});\n  }\n  clear() {\n    startMeasure('clear');\n    this.state.store.clear();\n    this.setState({store: this.state.store});\n  }\n  swapRows() {\n    startMeasure('swapRows');\n    this.state.store.swapRows();\n    this.setState({store: this.state.store});\n  }\n  render() {\n    let rows = this.state.store.data.map((d, i) => {\n      return <Row key={d.id} data={d} onClick={this.select} onDelete={this.delete} styleClass={d.id === this.state.store.selected ? 'danger' : ''} />;\n    });\n    return (<div className=\"container\">\n      <div className=\"jumbotron\">\n        <div className=\"row\">\n          <div className=\"col-md-6\">\n            <h1>preact</h1>\n          </div>\n          <div className=\"col-md-6\">\n            <div className=\"row\">\n              <div className=\"col-sm-6 smallpad\">\n                <button type=\"button\" className=\"btn btn-primary btn-block\" id=\"run\" onClick={this.run}>Create 1,000 rows</button>\n              </div>\n              <div className=\"col-sm-6 smallpad\">\n                <button type=\"button\" className=\"btn btn-primary btn-block\" id=\"runlots\" onClick={this.runLots}>Create 10,000 rows</button>\n              </div>\n              <div className=\"col-sm-6 smallpad\">\n                <button type=\"button\" className=\"btn btn-primary btn-block\" id=\"add\" onClick={this.add}>Append 1,000 rows</button>\n              </div>\n              <div className=\"col-sm-6 smallpad\">\n                <button type=\"button\" className=\"btn btn-primary btn-block\" id=\"update\" onClick={this.update}>Update every 10th row</button>\n              </div>\n              <div className=\"col-sm-6 smallpad\">\n                <button type=\"button\" className=\"btn btn-primary btn-block\" id=\"clear\" onClick={this.clear}>Clear</button>\n              </div>\n              <div className=\"col-sm-6 smallpad\">\n                <button type=\"button\" className=\"btn btn-primary btn-block\" id=\"swaprows\" onClick={this.swapRows}>Swap Rows</button>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n      <table className=\"table table-hover table-striped test-data\">\n        <tbody>\n          {rows}\n        </tbody>\n      </table>\n      <span className=\"preloadicon glyphicon glyphicon-remove\" aria-hidden=\"true\" />\n    </div>);\n  }\n}\n\nrender(<Main />, document.getElementById('main'));"
  },
  {
    "path": "scripts/bench/frameworks/preact/src/Row.jsx",
    "content": "'use strict';\n/** @jsx preact.h */\n\nvar preact = require('preact');\n\nvar { render, h, Component } = preact;\n\nexport class Row extends Component {\n  constructor(props) {\n    super(props);\n    this.onDelete = this.onDelete.bind(this);\n    this.onClick = this.onClick.bind(this);\n  }\n  shouldComponentUpdate(nextProps, nextState) {\n    return nextProps.data !== this.props.data || nextProps.styleClass !== this.props.styleClass;\n  }\n\n  onDelete() {\n    this.props.onDelete(this.props.data.id);\n  }\n  onClick() {\n    this.props.onClick(this.props.data.id);\n  }\n\n  render() {\n    let {styleClass, onClick, onDelete, data} = this.props;\n    return (<tr className={styleClass}>\n      <td className=\"col-md-1\">{data.id}</td>\n      <td className=\"col-md-4\">\n        <a onClick={this.onClick}>{data.label}</a>\n      </td>\n      <td className=\"col-md-1\"><a onClick={this.onDelete}><span className=\"glyphicon glyphicon-remove\" aria-hidden=\"true\">delete</span></a></td>\n      <td className=\"col-md-6\" />\n    </tr>);\n  }\n}\n\n"
  },
  {
    "path": "scripts/bench/frameworks/preact/src/Store.es6.js",
    "content": "'use strict';\n\nfunction _random(max) {\n  return Math.round(Math.random() * 1000) % max;\n}\n\nexport class Store {\n  constructor() {\n    this.data = [];\n    this.selected = undefined;\n    this.id = 1;\n  }\n  buildData(count = 1000) {\n    var adjectives = ['pretty', 'large', 'big', 'small', 'tall', 'short', 'long', 'handsome', 'plain', 'quaint', 'clean', 'elegant', 'easy', 'angry', 'crazy', 'helpful', 'mushy', 'odd', 'unsightly', 'adorable', 'important', 'inexpensive', 'cheap', 'expensive', 'fancy'];\n    var colours = ['red', 'yellow', 'blue', 'green', 'pink', 'brown', 'purple', 'brown', 'white', 'black', 'orange'];\n    var nouns = ['table', 'chair', 'house', 'bbq', 'desk', 'car', 'pony', 'cookie', 'sandwich', 'burger', 'pizza', 'mouse', 'keyboard'];\n    var data = [];\n    for (var i = 0; i < count; i++)\n      data.push({id: this.id++, label: adjectives[_random(adjectives.length)] + ' ' + colours[_random(colours.length)] + ' ' + nouns[_random(nouns.length)] });\n    return data;\n  }\n  updateData(mod = 10) {\n    for (let i = 0; i < this.data.length; i += 10) {\n      this.data[i] = Object.assign({}, this.data[i], {label: this.data[i].label + ' !!!'});\n    }\n  }\n  delete(id) {\n    var idx = this.data.findIndex(d => d.id === id);\n    this.data.splice(idx, 1);\n  }\n  run() {\n    this.data = this.buildData();\n    this.selected = undefined;\n  }\n  add() {\n    this.data = this.data.concat(this.buildData(1000));\n  }\n  update() {\n    this.updateData();\n  }\n  select(id) {\n    this.selected = id;\n  }\n  runLots() {\n    this.data = this.buildData(10000);\n    this.selected = undefined;\n  }\n  clear() {\n    this.data = [];\n    this.selected = undefined;\n  }\n  swapRows() {\n    if (this.data.length > 998) {\n      var a = this.data[1];\n      this.data[1] = this.data[998];\n      this.data[998] = a;\n    }\n  }\n}"
  },
  {
    "path": "scripts/bench/frameworks/preact/webpack.config.js",
    "content": "'use strict';\n\nconst path = require('path');\nconst webpack = require('webpack');\n\nconst loaders = [\n  {\n    test: /\\.jsx$/,\n    loader: 'babel-loader'\n  },\n  {\n    test: /\\.es6\\.js$/,\n    loader: 'babel-loader'\n  }\n];\nconst extensions = [\n  '.js', '.jsx', '.es6.js', '.msx'\n];\n\nmodule.exports = [{\n  mode: 'production',\n  module: {\n    rules: loaders\n  },\n  entry: {\n    main: './src/Main.jsx',\n  },\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: '[name].js',\n    sourceMapFilename: '[file].map',\n  },\n  resolve: {\n    extensions: extensions,\n    modules: [\n      __dirname,\n      path.resolve(__dirname, 'src'),\n      'node_modules'\n    ],\n    alias: {\n      'preact': 'node_modules/preact/dist/preact.min.js',\n    }\n  },\n  plugins: [\n    new webpack.DefinePlugin({\n      'process.env': {\n        'NODE_ENV': JSON.stringify('production')\n      }\n    })\n  ]\n}];"
  },
  {
    "path": "scripts/bench/frameworks/rax/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n  <meta charset=\"utf-8\" />\n  <title>Rax</title>\n  <link href=\"/css/currentStyle.css\" rel=\"stylesheet\" />\n</head>\n\n<body>\n  <div id='main'></div>\n  <script src='dist/main.js'></script>\n</body>\n\n</html>"
  },
  {
    "path": "scripts/bench/frameworks/rax/package.json",
    "content": "{\n  \"name\": \"js-framework-benchmark-rax\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Benchmark for rax\",\n  \"scripts\": {\n    \"build-dev\": \"webpack --watch\",\n    \"build-prod\": \"webpack\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"7.1.2\",\n    \"@babel/preset-env\": \"7.1.0\",\n    \"@babel/preset-react\": \"7.0.0\",\n    \"babel-loader\": \"8.0.4\",\n    \"webpack\": \"4.22.0\",\n    \"webpack-cli\": \"3.1.2\"\n  },\n  \"dependencies\": {\n    \"driver-dom\": \"^1.0.0\",\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "scripts/bench/frameworks/rax/src/main.jsx",
    "content": "/**\n * @jsx createElement\n */\nimport { createElement, memo, useReducer, useCallback, render } from 'rax';\nimport * as DriverDOM from 'driver-dom';\n\nfunction random(max) {\n  return Math.round(Math.random() * 1000) % max;\n}\n\nconst A = ['pretty', 'large', 'big', 'small', 'tall', 'short', 'long', 'handsome', 'plain', 'quaint', 'clean',\n  'elegant', 'easy', 'angry', 'crazy', 'helpful', 'mushy', 'odd', 'unsightly', 'adorable', 'important', 'inexpensive',\n  'cheap', 'expensive', 'fancy'];\nconst C = ['red', 'yellow', 'blue', 'green', 'pink', 'brown', 'purple', 'brown', 'white', 'black', 'orange'];\nconst N = ['table', 'chair', 'house', 'bbq', 'desk', 'car', 'pony', 'cookie', 'sandwich', 'burger', 'pizza', 'mouse',\n  'keyboard'];\n\nlet nextId = 1;\n\nfunction buildData(count) {\n  const data = new Array(count);\n  for (let i = 0; i < count; i++) {\n    data[i] = {\n      id: nextId++,\n      label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`,\n    };\n  }\n  return data;\n}\n\nfunction listReducer(state, action) {\n  const { data, selected } = state;\n  switch (action.type) {\n    case 'RUN':\n      return { data: buildData(1000), selected: 0 };\n    case 'RUN_LOTS':\n      return { data: buildData(10000), selected: 0 };\n    case 'ADD':\n      return { data: data.concat(buildData(1000)), selected };\n    case 'UPDATE':\n      const newData = data.slice(0);\n      for (let i = 0; i < newData.length; i += 10) {\n        const r = newData[i];\n        newData[i] = { id: r.id, label: r.label + ' !!!' };\n      }\n      return { data: newData, selected };\n    case 'CLEAR':\n      return { data: [], selected: 0 };\n    case 'SWAP_ROWS':\n      return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected };\n    case 'REMOVE':\n      const idx = data.findIndex((d) => d.id === action.id);\n      return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected };\n    case 'SELECT':\n      return { data, selected: action.id };\n  }\n  return state;\n}\n\nconst GlyphIcon = <span className=\"glyphicon glyphicon-remove\" aria-hidden=\"true\">delete</span>;\n\nconst Row = memo(({ selected, item, dispatch }) => {\n  const select = useCallback(() => dispatch({ type: 'SELECT', id: item.id }), []),\n    remove = useCallback(() => dispatch({ type: 'REMOVE', id: item.id }), []);\n\n  return (<tr className={selected ? 'danger' : ''}>\n    <td className=\"col-md-1\">{item.id}</td>\n    <td className=\"col-md-4\"><a onClick={select}>{item.label}</a></td>\n    <td className=\"col-md-1\"><a onClick={remove}>{GlyphIcon}</a></td>\n    <td className=\"col-md-6\" />\n  </tr>);\n});\n\nconst Button = ({ id, cb, title }) => (\n  <div className=\"col-sm-6 smallpad\">\n    <button type=\"button\" className=\"btn btn-primary btn-block\" id={id} onClick={cb}>{title}</button>\n  </div>\n);\n\nconst Jumbotron = memo(({ dispatch }) =>\n  <div className=\"jumbotron\">\n    <div className=\"row\">\n      <div className=\"col-md-6\">\n        <h1>Rax</h1>\n      </div>\n      <div className=\"col-md-6\">\n        <div className=\"row\">\n          <Button id=\"run\" title=\"Create 1,000 rows\" cb={() => dispatch({ type: 'RUN' })} />\n          <Button id=\"runlots\" title=\"Create 10,000 rows\" cb={() => dispatch({ type: 'RUN_LOTS' })} />\n          <Button id=\"add\" title=\"Append 1,000 rows\" cb={() => dispatch({ type: 'ADD' })} />\n          <Button id=\"update\" title=\"Update every 10th row\" cb={() => dispatch({ type: 'UPDATE' })} />\n          <Button id=\"clear\" title=\"Clear\" cb={() => dispatch({ type: 'CLEAR' })} />\n          <Button id=\"swaprows\" title=\"Swap Rows\" cb={() => dispatch({ type: 'SWAP_ROWS' })} />\n        </div>\n      </div>\n    </div>\n  </div>\n, () => true);\n\nconst Main = () => {\n  const [state, dispatch] = useReducer(listReducer, { data: [], selected: 0 });\n\n  return (<div className=\"container\">\n    <Jumbotron dispatch={dispatch} />\n    <table className=\"table table-hover table-striped test-data\"><tbody>\n      {state.data.map(item => (\n        <Row key={item.id} item={item} selected={state.selected === item.id} dispatch={dispatch} />\n      ))}\n    </tbody></table>\n    <span className=\"preloadicon glyphicon glyphicon-remove\" aria-hidden=\"true\" />\n  </div>);\n};\n\nrender(<Main />, document.getElementById('main'), { driver: DriverDOM });"
  },
  {
    "path": "scripts/bench/frameworks/rax/webpack.config.js",
    "content": "const path = require('path');\nconst webpack = require('webpack');\n\nmodule.exports = {\n  mode: 'production',\n  // mode: 'development',\n  entry: {\n    main: path.join(__dirname, 'src', 'main.jsx'),\n  },\n  output: {\n    path: path.join(__dirname, 'dist'),\n    filename: '[name].js'\n  },\n  resolve: {\n    extensions: ['.js', '.jsx']\n  },\n  module: {\n    rules: [{\n      test: /\\.jsx?$/,\n      exclude: /node_modules/,\n      use: [\n        {\n          loader: 'babel-loader',\n          options: {\n            presets: [\n              [\n                '@babel/preset-env',\n                {\n                  targets: {\n                    browsers: ['last 1 chrome versions']\n                  },\n                  loose: true\n                }\n              ], '@babel/preset-react'\n            ]\n          }\n        }\n      ]\n    }]\n  },\n  plugins: [\n    new webpack.DefinePlugin({\n      'process.env': { NODE_ENV: JSON.stringify('production') }\n    })\n  ],\n};\n"
  },
  {
    "path": "scripts/bench/frameworks/rax-local/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n  <meta charset=\"utf-8\" />\n  <title>Rax</title>\n  <link href=\"/css/currentStyle.css\" rel=\"stylesheet\" />\n</head>\n\n<body>\n  <div id='main'></div>\n  <script src='dist/main.js'></script>\n</body>\n\n</html>"
  },
  {
    "path": "scripts/bench/frameworks/rax-local/package.json",
    "content": "{\n  \"name\": \"js-framework-benchmark-rax-local\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Benchmark for rax(local)\",\n  \"scripts\": {\n    \"build-dev\": \"webpack --watch\",\n    \"build-prod\": \"webpack\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"7.1.2\",\n    \"@babel/preset-env\": \"7.1.0\",\n    \"@babel/preset-react\": \"7.0.0\",\n    \"babel-loader\": \"8.0.4\",\n    \"webpack\": \"4.22.0\",\n    \"webpack-cli\": \"3.1.2\"\n  },\n  \"dependencies\": {\n    \"driver-dom\": \"^1.0.0\",\n    \"rax\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "scripts/bench/frameworks/rax-local/src/main.jsx",
    "content": "/**\n * @jsx createElement\n */\nimport { createElement, memo, useReducer, useCallback, render } from '../../../../../packages/rax';\nimport * as DriverDOM from '../../../../../packages/driver-dom';\n\nfunction random(max) {\n  return Math.round(Math.random() * 1000) % max;\n}\n\nconst A = ['pretty', 'large', 'big', 'small', 'tall', 'short', 'long', 'handsome', 'plain', 'quaint', 'clean',\n  'elegant', 'easy', 'angry', 'crazy', 'helpful', 'mushy', 'odd', 'unsightly', 'adorable', 'important', 'inexpensive',\n  'cheap', 'expensive', 'fancy'];\nconst C = ['red', 'yellow', 'blue', 'green', 'pink', 'brown', 'purple', 'brown', 'white', 'black', 'orange'];\nconst N = ['table', 'chair', 'house', 'bbq', 'desk', 'car', 'pony', 'cookie', 'sandwich', 'burger', 'pizza', 'mouse',\n  'keyboard'];\n\nlet nextId = 1;\n\nfunction buildData(count) {\n  const data = new Array(count);\n  for (let i = 0; i < count; i++) {\n    data[i] = {\n      id: nextId++,\n      label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`,\n    };\n  }\n  return data;\n}\n\nfunction listReducer(state, action) {\n  const { data, selected } = state;\n  switch (action.type) {\n    case 'RUN':\n      return { data: buildData(1000), selected: 0 };\n    case 'RUN_LOTS':\n      return { data: buildData(10000), selected: 0 };\n    case 'ADD':\n      return { data: data.concat(buildData(1000)), selected };\n    case 'UPDATE':\n      const newData = data.slice(0);\n      for (let i = 0; i < newData.length; i += 10) {\n        const r = newData[i];\n        newData[i] = { id: r.id, label: r.label + ' !!!' };\n      }\n      return { data: newData, selected };\n    case 'CLEAR':\n      return { data: [], selected: 0 };\n    case 'SWAP_ROWS':\n      return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected };\n    case 'REMOVE':\n      const idx = data.findIndex((d) => d.id === action.id);\n      return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected };\n    case 'SELECT':\n      return { data, selected: action.id };\n  }\n  return state;\n}\n\nconst GlyphIcon = <span className=\"glyphicon glyphicon-remove\" aria-hidden=\"true\">delete</span>;\n\nconst Row = memo(({ selected, item, dispatch }) => {\n  const select = useCallback(() => dispatch({ type: 'SELECT', id: item.id }), []),\n    remove = useCallback(() => dispatch({ type: 'REMOVE', id: item.id }), []);\n\n  return (<tr className={selected ? 'danger' : ''}>\n    <td className=\"col-md-1\">{item.id}</td>\n    <td className=\"col-md-4\"><a onClick={select}>{item.label}</a></td>\n    <td className=\"col-md-1\"><a onClick={remove}>{GlyphIcon}</a></td>\n    <td className=\"col-md-6\" />\n  </tr>);\n});\n\nconst Button = ({ id, cb, title }) => (\n  <div className=\"col-sm-6 smallpad\">\n    <button type=\"button\" className=\"btn btn-primary btn-block\" id={id} onClick={cb}>{title}</button>\n  </div>\n);\n\nconst Jumbotron = memo(({ dispatch }) =>\n  <div className=\"jumbotron\">\n    <div className=\"row\">\n      <div className=\"col-md-6\">\n        <h1>Rax(local)</h1>\n      </div>\n      <div className=\"col-md-6\">\n        <div className=\"row\">\n          <Button id=\"run\" title=\"Create 1,000 rows\" cb={() => dispatch({ type: 'RUN' })} />\n          <Button id=\"runlots\" title=\"Create 10,000 rows\" cb={() => dispatch({ type: 'RUN_LOTS' })} />\n          <Button id=\"add\" title=\"Append 1,000 rows\" cb={() => dispatch({ type: 'ADD' })} />\n          <Button id=\"update\" title=\"Update every 10th row\" cb={() => dispatch({ type: 'UPDATE' })} />\n          <Button id=\"clear\" title=\"Clear\" cb={() => dispatch({ type: 'CLEAR' })} />\n          <Button id=\"swaprows\" title=\"Swap Rows\" cb={() => dispatch({ type: 'SWAP_ROWS' })} />\n        </div>\n      </div>\n    </div>\n  </div>\n, () => true);\n\nconst Main = () => {\n  const [state, dispatch] = useReducer(listReducer, { data: [], selected: 0 });\n\n  return (<div className=\"container\">\n    <Jumbotron dispatch={dispatch} />\n    <table className=\"table table-hover table-striped test-data\"><tbody>\n      {state.data.map(item => (\n        <Row key={item.id} item={item} selected={state.selected === item.id} dispatch={dispatch} />\n      ))}\n    </tbody></table>\n    <span className=\"preloadicon glyphicon glyphicon-remove\" aria-hidden=\"true\" />\n  </div>);\n};\n\nrender(<Main />, document.getElementById('main'), { driver: DriverDOM });\n"
  },
  {
    "path": "scripts/bench/frameworks/rax-local/webpack.config.js",
    "content": "const path = require('path');\nconst webpack = require('webpack');\n\nmodule.exports = {\n  mode: 'production',\n  // mode: 'development',\n  entry: {\n    main: path.join(__dirname, 'src', 'main.jsx'),\n  },\n  output: {\n    path: path.join(__dirname, 'dist'),\n    filename: '[name].js'\n  },\n  resolve: {\n    extensions: ['.js', '.jsx']\n  },\n  module: {\n    rules: [{\n      test: /\\.jsx?$/,\n      exclude: /node_modules/,\n      use: [\n        {\n          loader: 'babel-loader',\n          options: {\n            presets: [\n              [\n                '@babel/preset-env',\n                {\n                  targets: {\n                    browsers: ['last 1 chrome versions']\n                  },\n                  loose: true\n                }\n              ], '@babel/preset-react'\n            ]\n          }\n        }\n      ]\n    }]\n  },\n  plugins: [\n    new webpack.DefinePlugin({\n      'process.env': { NODE_ENV: JSON.stringify('production') }\n    })\n  ],\n};\n"
  },
  {
    "path": "scripts/bench/frameworks/vanillajs/.babelrc",
    "content": "{\n  \"presets\": [\n    [\n      \"@babel/preset-env\",\n      {\n        \"targets\": {\n          \"browsers\": [\"last 1 chrome versions\"]\n        },\n        \"loose\" : true\n      }\n    ]\n  ],\n  \"plugins\": []\n}\n"
  },
  {
    "path": "scripts/bench/frameworks/vanillajs/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\"/>\n    <title>VanillaJS</title>\n    <link href=\"/css/currentStyle.css\" rel=\"stylesheet\"/>\n</head>\n<body>\n<div id='main'>\n    <div class=\"container\">\n        <div class=\"jumbotron\">\n            <div class=\"row\">\n                <div class=\"col-md-6\">\n                    <h1>VanillaJS</h1>\n                </div>\n                <div class=\"col-md-6\">\n                    <div class=\"row\">\n                        <div class=\"col-sm-6 smallpad\">\n                            <button type='button' class='btn btn-primary btn-block' id='run'>Create 1,000 rows</button>\n                        </div>\n                        <div class=\"col-sm-6 smallpad\">\n                            <button type='button' class='btn btn-primary btn-block' id='runlots'>Create 10,000 rows</button>\n                        </div>\n                        <div class=\"col-sm-6 smallpad\">\n                            <button type='button' class='btn btn-primary btn-block' id='add'>Append 1,000 rows</button>\n                        </div>\n                        <div class=\"col-sm-6 smallpad\">\n                            <button type='button' class='btn btn-primary btn-block' id='update'>Update every 10th row</button>\n                        </div>\n                        <div class=\"col-sm-6 smallpad\">\n                            <button type='button' class='btn btn-primary btn-block' id='clear'>Clear</button>\n                        </div>\n                        <div class=\"col-sm-6 smallpad\">\n                            <button type='button' class='btn btn-primary btn-block' id='swaprows'>Swap Rows</button>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n        <table class=\"table table-hover table-striped test-data\">\n            <tbody id=\"tbody\">\n            </tbody>\n        </table>\n        <span class=\"preloadicon glyphicon glyphicon-remove\" aria-hidden=\"true\"></span>\n    </div>\n</div>\n<script src='dist/main.js'></script>\n</body>\n</html>\n"
  },
  {
    "path": "scripts/bench/frameworks/vanillajs/package.json",
    "content": "{\n  \"name\": \"js-framework-benchmark-vanillajs\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Benchmark for vanillajs\",\n  \"scripts\": {\n    \"build-dev\": \"webpack -w -d\",\n    \"build-prod\": \"webpack -p\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"7.1.2\",\n    \"@babel/preset-env\": \"7.1.0\",\n    \"@babel/preset-react\": \"7.0.0\",\n    \"babel-loader\": \"8.0.4\",\n    \"webpack\": \"4.22.0\",\n    \"webpack-cli\": \"3.1.2\"\n  }\n}\n"
  },
  {
    "path": "scripts/bench/frameworks/vanillajs/src/Main.js",
    "content": "'use strict';\n\nvar startTime;\nvar lastMeasure;\nvar startMeasure = function(name) {\n  startTime = performance.now();\n  lastMeasure = name;\n};\nvar stopMeasure = function() {\n  var last = lastMeasure;\n  if (lastMeasure) {\n    window.setTimeout(function() {\n      lastMeasure = null;\n      var stop = performance.now();\n      var duration = 0;\n      console.log(last + ' took ' + (stop - startTime));\n    }, 0);\n  }\n};\n\nfunction _random(max) {\n  return Math.round(Math.random() * 1000) % max;\n}\n\nconst rowTemplate = document.createElement('tr');\nrowTemplate.innerHTML = \"<td class='col-md-1'></td><td class='col-md-4'><a class='lbl'></a></td><td class='col-md-1'><a class='remove'><span class='remove glyphicon glyphicon-remove' aria-hidden='true'>delete</span></a></td><td class='col-md-6'></td>\";\n\nclass Store {\n  constructor() {\n    this.data = [];\n    this.backup = null;\n    this.selected = null;\n    this.id = 1;\n  }\n  buildData(count = 1000) {\n    var adjectives = ['pretty', 'large', 'big', 'small', 'tall', 'short', 'long', 'handsome', 'plain', 'quaint', 'clean', 'elegant', 'easy', 'angry', 'crazy', 'helpful', 'mushy', 'odd', 'unsightly', 'adorable', 'important', 'inexpensive', 'cheap', 'expensive', 'fancy'];\n    var colours = ['red', 'yellow', 'blue', 'green', 'pink', 'brown', 'purple', 'brown', 'white', 'black', 'orange'];\n    var nouns = ['table', 'chair', 'house', 'bbq', 'desk', 'car', 'pony', 'cookie', 'sandwich', 'burger', 'pizza', 'mouse', 'keyboard'];\n    var data = [];\n    for (var i = 0; i < count; i++)\n      data.push({id: this.id++, label: adjectives[_random(adjectives.length)] + ' ' + colours[_random(colours.length)] + ' ' + nouns[_random(nouns.length)] });\n    return data;\n  }\n  updateData(mod = 10) {\n    for (let i = 0; i < this.data.length; i += 10) {\n      this.data[i].label += ' !!!';\n      // this.data[i] = Object.assign({}, this.data[i], {label: this.data[i].label +' !!!'});\n    }\n  }\n  delete(id) {\n    const idx = this.data.findIndex(d => d.id == id);\n    this.data = this.data.filter((e, i) => i != idx);\n    return this;\n  }\n  run() {\n    this.data = this.buildData();\n    this.selected = null;\n  }\n  add() {\n    this.data = this.data.concat(this.buildData(1000));\n    this.selected = null;\n  }\n  update() {\n    this.updateData();\n    this.selected = null;\n  }\n  select(id) {\n    this.selected = id;\n  }\n  hideAll() {\n    this.backup = this.data;\n    this.data = [];\n    this.selected = null;\n  }\n  showAll() {\n    this.data = this.backup;\n    this.backup = null;\n    this.selected = null;\n  }\n  runLots() {\n    this.data = this.buildData(10000);\n    this.selected = null;\n  }\n  clear() {\n    this.data = [];\n    this.selected = null;\n  }\n  swapRows() {\n    if (this.data.length > 998) {\n      var a = this.data[1];\n      this.data[1] = this.data[998];\n      this.data[998] = a;\n    }\n  }\n}\n\nvar getParentId = function(elem) {\n  while (elem) {\n    if (elem.tagName === 'TR') {\n      return elem.data_id;\n    }\n    elem = elem.parentNode;\n  }\n  return undefined;\n};\nclass Main {\n  constructor(props) {\n    this.store = new Store();\n    this.select = this.select.bind(this);\n    this.delete = this.delete.bind(this);\n    this.add = this.add.bind(this);\n    this.run = this.run.bind(this);\n    this.update = this.update.bind(this);\n    this.start = 0;\n    this.rows = [];\n    this.data = [];\n    this.selectedRow = undefined;\n\n    document.getElementById('main').addEventListener('click', e => {\n      // console.log(\"listener\",e);\n      if (e.target.matches('#add')) {\n        e.preventDefault();\n        // console.log(\"add\");\n        this.add();\n      } else if (e.target.matches('#run')) {\n        e.preventDefault();\n        // console.log(\"run\");\n        this.run();\n      } else if (e.target.matches('#update')) {\n        e.preventDefault();\n        // console.log(\"update\");\n        this.update();\n      } else if (e.target.matches('#hideall')) {\n        e.preventDefault();\n        // console.log(\"hideAll\");\n        this.hideAll();\n      } else if (e.target.matches('#showall')) {\n        e.preventDefault();\n        // console.log(\"showAll\");\n        this.showAll();\n      } else if (e.target.matches('#runlots')) {\n        e.preventDefault();\n        // console.log(\"runLots\");\n        this.runLots();\n      } else if (e.target.matches('#clear')) {\n        e.preventDefault();\n        // console.log(\"clear\");\n        this.clear();\n      } else if (e.target.matches('#swaprows')) {\n        e.preventDefault();\n        // console.log(\"swapRows\");\n        this.swapRows();\n      } else if (e.target.matches('.remove')) {\n        e.preventDefault();\n        let id = getParentId(e.target);\n        let idx = this.findIdx(id);\n        // console.log(\"delete\",idx);\n        this.delete(idx);\n      } else if (e.target.matches('.lbl')) {\n        e.preventDefault();\n        let id = getParentId(e.target);\n        let idx = this.findIdx(id);\n        // console.log(\"select\",idx);\n        this.select(idx);\n      }\n    });\n    this.tbody = document.getElementById('tbody');\n  }\n  findIdx(id) {\n    for (let i = 0; i < this.data.length; i++) {\n      if (this.data[i].id === id) return i;\n    }\n    return undefined;\n  }\n  printDuration() {\n    stopMeasure();\n  }\n  run() {\n    startMeasure('run');\n    this.removeAllRows();\n    this.store.clear();\n    this.rows = [];\n    this.data = [];\n    this.store.run();\n    this.appendRows();\n    this.unselect();\n    stopMeasure();\n  }\n  add() {\n    startMeasure('add');\n    this.store.add();\n    this.appendRows();\n    stopMeasure();\n  }\n  update() {\n    startMeasure('update');\n    this.store.update();\n    for (let i = 0; i < this.data.length; i += 10) {\n      this.rows[i].childNodes[1].childNodes[0].innerText = this.store.data[i].label;\n    }\n    stopMeasure();\n  }\n  unselect() {\n    if (this.selectedRow !== undefined) {\n      this.selectedRow.className = '';\n      this.selectedRow = undefined;\n    }\n  }\n  select(idx) {\n    startMeasure('select');\n    this.unselect();\n    this.store.select(this.data[idx].id);\n    this.selectedRow = this.rows[idx];\n    this.selectedRow.className = 'danger';\n    stopMeasure();\n  }\n  recreateSelection() {\n    let old_selection = this.store.selected;\n    let sel_idx = this.store.data.findIndex(d => d.id === old_selection);\n    if (sel_idx >= 0) {\n      this.store.select(this.data[sel_idx].id);\n      this.selectedRow = this.rows[sel_idx];\n      this.selectedRow.className = 'danger';\n    }\n  }\n  delete(idx) {\n    startMeasure('delete');\n    // Remove that row from the DOM\n    this.store.delete(this.data[idx].id);\n    this.rows[idx].remove();\n    this.rows.splice(idx, 1);\n    this.data.splice(idx, 1);\n    this.unselect();\n    this.recreateSelection();\n    stopMeasure();\n  }\n  removeAllRows() {\n    // ~258 msecs\n    // for(let i=this.rows.length-1;i>=0;i--) {\n    //     tbody.removeChild(this.rows[i]);\n    // }\n    // ~251 msecs\n    // for(let i=0;i<this.rows.length;i++) {\n    //     tbody.removeChild(this.rows[i]);\n    // }\n    // ~216 msecs\n    // var cNode = tbody.cloneNode(false);\n    // tbody.parentNode.replaceChild(cNode ,tbody);\n    // ~212 msecs\n    this.tbody.textContent = '';\n\n    // ~236 msecs\n    // var rangeObj = new Range();\n    // rangeObj.selectNodeContents(tbody);\n    // rangeObj.deleteContents();\n    // ~260 msecs\n    // var last;\n    // while (last = tbody.lastChild) tbody.removeChild(last);\n  }\n  runLots() {\n    startMeasure('runLots');\n    this.removeAllRows();\n    this.store.clear();\n    this.rows = [];\n    this.data = [];\n    this.store.runLots();\n    this.appendRows();\n    this.unselect();\n    stopMeasure();\n  }\n  clear() {\n    startMeasure('clear');\n    this.store.clear();\n    this.rows = [];\n    this.data = [];\n    // This is actually a bit faster, but close to cheating\n    // requestAnimationFrame(() => {\n    this.removeAllRows();\n    this.unselect();\n    stopMeasure();\n    // });\n  }\n  swapRows() {\n    startMeasure('swapRows');\n    if (this.data.length > 10) {\n      this.store.swapRows();\n      this.data[1] = this.store.data[1];\n      this.data[998] = this.store.data[998];\n\n      this.tbody.insertBefore(this.rows[998], this.rows[2]);\n      this.tbody.insertBefore(this.rows[1], this.rows[999]);\n\n      let tmp = this.rows[998];\n      this.rows[998] = this.rows[1];\n      this.rows[1] = tmp;\n    }\n\n\n    // let old_selection = this.store.selected;\n    // this.store.swapRows();\n    // this.updateRows();\n    // this.unselect();\n    // if (old_selection>=0) {\n    //     let idx = this.store.data.findIndex(d => d.id === old_selection);\n    //     if (idx > 0) {\n    //         this.store.select(this.data[idx].id);\n    //         this.selectedRow = this.rows[idx];\n    //         this.selectedRow.className = \"danger\";\n    //     }\n    // }\n    stopMeasure();\n  }\n  appendRows() {\n    // Using a document fragment is slower...\n    // var docfrag = document.createDocumentFragment();\n    // for(let i=this.rows.length;i<this.store.data.length; i++) {\n    //     let tr = this.createRow(this.store.data[i]);\n    //     this.rows[i] = tr;\n    //     this.data[i] = this.store.data[i];\n    //     docfrag.appendChild(tr);\n    // }\n    // this.tbody.appendChild(docfrag);\n\n    // ... than adding directly\n    var rows = this.rows, s_data = this.store.data, data = this.data, tbody = this.tbody;\n    for (let i = rows.length; i < s_data.length; i++) {\n      let tr = this.createRow(s_data[i]);\n      rows[i] = tr;\n      data[i] = s_data[i];\n      tbody.appendChild(tr);\n    }\n  }\n  createRow(data) {\n    const tr = rowTemplate.cloneNode(true),\n      td1 = tr.firstChild,\n      a2 = td1.nextSibling.firstChild;\n    tr.data_id = data.id;\n    td1.textContent = data.id;\n    a2.textContent = data.label;\n    return tr;\n  }\n}\n\nnew Main();\n"
  },
  {
    "path": "scripts/bench/frameworks/vanillajs/webpack.config.js",
    "content": "'use strict';\nconst path = require('path');\nconst webpack = require('webpack');\n\nconst rules = [\n  {\n    test: /\\.js$/,\n    loader: 'babel-loader'\n  }\n];\nconst extensions = [\n  '.js', '.jsx', '.es6.js'\n];\n\nmodule.exports = [{\n  mode: 'production',\n  module: {\n    rules: rules\n  },\n  entry: {\n    main: './src/Main.js',\n  },\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: '[name].js'\n  },\n  resolve: {\n    extensions: extensions,\n    modules: [\n      __dirname,\n      path.resolve(__dirname, 'src'),\n      'node_modules'\n    ],\n    alias: {\n    }\n  },\n  plugins: [\n    new webpack.DefinePlugin({\n      'process.env': { NODE_ENV: JSON.stringify('production') }\n    })\n  ],\n}];"
  },
  {
    "path": "scripts/bench/frameworks/vue/.babelrc",
    "content": "{\n  \"presets\": [\n    [\n      \"@babel/preset-env\",\n      {\n        \"targets\": {\n          \"browsers\": [\"last 1 chrome versions\"]\n        },\n        \"loose\" : true\n      }\n    ]\n  ],\n  \"plugins\": []\n}\n"
  },
  {
    "path": "scripts/bench/frameworks/vue/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Vue.js</title>\n  <link href=\"/css/currentStyle.css\" rel=\"stylesheet\"/>\n</head>\n<body>\n  <div id='main'></div>\n  <script src='dist/main.js'></script>\n</body>\n</html>\n"
  },
  {
    "path": "scripts/bench/frameworks/vue/package.json",
    "content": "{\n  \"name\": \"js-framework-benchmark-vue\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Benchmark for vue.js framework\",\n  \"scripts\": {\n    \"build-dev\": \"webpack -w -d\",\n    \"build-prod\": \"webpack -p\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"7.2.2\",\n    \"@babel/preset-env\": \"7.3.1\",\n    \"css-loader\": \"2.1.0\",\n    \"vue-loader\": \"15.6.2\",\n    \"babel-loader\": \"8.0.5\",\n    \"vue-template-compiler\": \"^2.6.2\",\n    \"webpack\": \"4.29.2\",\n    \"webpack-cli\": \"3.2.3\"\n  },\n  \"dependencies\": {\n    \"vue\": \"^2.6.2\"\n  }\n}\n"
  },
  {
    "path": "scripts/bench/frameworks/vue/src/App.vue",
    "content": "<template>\n    <div class=\"container\">\n        <div class=\"jumbotron\">\n            <div class=\"row\">\n                <div class=\"col-md-6\">\n                    <h1>Vue.js</h1>\n                </div>\n                <div class=\"col-md-6\">\n                    <div class=\"row\">\n                        <div class=\"col-sm-6 smallpad\">\n                          <button type=\"button\" class=\"btn btn-primary btn-block\" id=\"run\" v-on:click=\"run\">Create 1,000 rows</button>\n                        </div>\n                        <div class=\"col-sm-6 smallpad\">\n                            <button type=\"button\" class=\"btn btn-primary btn-block\" id=\"runlots\" v-on:click=\"runLots\">Create 10,000 rows</button>\n                        </div>\n                        <div class=\"col-sm-6 smallpad\">\n                            <button type=\"button\" class=\"btn btn-primary btn-block\" id=\"add\" v-on:click=\"add\">Append 1,000 rows</button>\n                        </div>\n                        <div class=\"col-sm-6 smallpad\">\n                            <button type=\"button\" class=\"btn btn-primary btn-block\" id=\"update\" v-on:click=\"update\">Update every 10th row</button>\n                        </div>\n                        <div class=\"col-sm-6 smallpad\">\n                            <button type=\"button\" class=\"btn btn-primary btn-block\" id=\"clear\" v-on:click=\"clear\">Clear</button>\n                        </div>\n                        <div class=\"col-sm-6 smallpad\">\n                            <button type=\"button\" class=\"btn btn-primary btn-block\" id=\"swaprows\" v-on:click=\"swapRows\">Swap Rows</button>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n        <table class=\"table table-hover table-striped test-data\" @click=\"handleClick\">\n            <tbody>\n                <tr v-for=\"item in rows\" :key=\"item.id\" :class=\"{'danger': item.id == selected}\">\n                    <td class=\"col-md-1\">{{item.id}}</td>\n                    <td class=\"col-md-4\">\n                        <a data-action=\"select\" :data-id=\"item.id\">{{item.label}}</a>\n                    </td>\n                    <td class=\"col-md-1\">\n                        <a>\n                            <span class=\"glyphicon glyphicon-remove\" aria-hidden=\"true\"\n                                data-action=\"remove\" :data-id=\"item.id\">delete</span>\n                        </a>\n                    </td>\n                    <td class=\"col-md-6\"></td>\n                </tr>\n            </tbody>\n        </table>\n        <span class=\"preloadicon glyphicon glyphicon-remove\" aria-hidden=\"true\"></span>\n    </div>\n</template>\n\n<script>\nimport { Store } from './store';\n\nvar store = new Store();\n\nvar startTime;\nvar lastMeasure;\nvar startMeasure = function(name) {\n    startTime = performance.now();\n    lastMeasure = name;\n}\nvar stopMeasure = function() {\n    var last = lastMeasure;\n    if (lastMeasure) {\n        window.setTimeout(function () {\n            lastMeasure = null;\n            var stop = performance.now();\n            console.log(last+\" took \"+(stop-startTime));\n        }, 0);\n    }\n}\n\nexport default {\n    data: () => ({\n        rows: store.data,\n        selected: store.selected\n    }),\n    methods: {\n        handleClick (e) {\n            const { action, id } = e.target.dataset\n            if (action && id) {\n                this[action](id)\n            }\n        },\n        add() {\n            startMeasure(\"add\");\n            store.add();\n            this.sync();\n            stopMeasure();\n        },\n        remove(id) {\n            startMeasure(\"remove\");\n            store.delete(id);\n            this.sync();\n            stopMeasure();\n        },\n        select(id) {\n            startMeasure(\"select\");\n            store.select(id);\n            this.sync();\n            stopMeasure();\n        },\n        run() {\n            startMeasure(\"run\");\n            store.run();\n            this.sync();\n            stopMeasure();\n        },\n        update() {\n            startMeasure(\"update\");\n            store.update();\n            this.sync();\n            stopMeasure();\n        },\n        runLots() {\n            startMeasure(\"runLots\");\n            store.runLots();\n            this.sync();\n            stopMeasure();\n        },\n        clear() {\n            startMeasure(\"clear\");\n            store.clear();\n            this.sync();\n            stopMeasure();\n        },\n        swapRows() {\n            startMeasure(\"swapRows\");\n            store.swapRows();\n            this.sync();\n            stopMeasure();\n        },\n        sync() {\n            this.rows = Object.freeze(store.data);\n            this.selected = store.selected;\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "scripts/bench/frameworks/vue/src/main.es6.js",
    "content": "import Vue from 'vue';\nimport App from './App.vue';\n\nnew Vue({\n  el: '#main',\n  render: h => h(App)\n});\n"
  },
  {
    "path": "scripts/bench/frameworks/vue/src/store.es6.js",
    "content": "'use strict';\n\nfunction _random(max) {\n  return Math.round(Math.random() * 1000) % max;\n}\n\nexport class Store {\n  constructor() {\n    this.data = [];\n    this.selected = undefined;\n    this.id = 1;\n  }\n  buildData(count = 1000) {\n    var adjectives = ['pretty', 'large', 'big', 'small', 'tall', 'short', 'long', 'handsome', 'plain', 'quaint', 'clean', 'elegant', 'easy', 'angry', 'crazy', 'helpful', 'mushy', 'odd', 'unsightly', 'adorable', 'important', 'inexpensive', 'cheap', 'expensive', 'fancy'];\n    var colours = ['red', 'yellow', 'blue', 'green', 'pink', 'brown', 'purple', 'brown', 'white', 'black', 'orange'];\n    var nouns = ['table', 'chair', 'house', 'bbq', 'desk', 'car', 'pony', 'cookie', 'sandwich', 'burger', 'pizza', 'mouse', 'keyboard'];\n    var data = [];\n    for (var i = 0; i < count; i++)\n      data.push({id: this.id++, label: adjectives[_random(adjectives.length)] + ' ' + colours[_random(colours.length)] + ' ' + nouns[_random(nouns.length)] });\n    return data;\n  }\n  updateData(mod = 10) {\n    // Just assigning setting each tenth this.data doesn't cause a redraw, the following does:\n    var newData = [...this.data];\n\n    for (let i = 0; i < newData.length; i += 10) {\n      newData[i].label += ' !!!';\n    }\n    this.data = newData;\n  }\n  delete(id) {\n    const idx = this.data.findIndex(d => d.id == id);\n    this.data = this.data.slice(0, idx).concat(this.data.slice(idx + 1));\n  }\n  run() {\n    this.data = this.buildData();\n    this.selected = undefined;\n  }\n  add() {\n    this.data = this.data.concat(this.buildData(1000));\n  }\n  update() {\n    this.updateData();\n  }\n  select(id) {\n    this.selected = id;\n  }\n  runLots() {\n    this.data = this.buildData(10000);\n    this.selected = undefined;\n  }\n  clear() {\n    this.data = [];\n    this.selected = undefined;\n  }\n  swapRows() {\n    if (this.data.length > 998) {\n      let d1 = this.data[1];\n      let d998 = this.data[998];\n\n      var newData = this.data.map(function(data, i) {\n        if (i === 1) {\n          return d998;\n        } else if (i === 998) {\n          return d1;\n        }\n        return data;\n      });\n      this.data = newData;\n    }\n  }\n}\n"
  },
  {
    "path": "scripts/bench/frameworks/vue/webpack.config.js",
    "content": "'use strict';\nconst path = require('path');\nconst webpack = require('webpack');\nconst VueLoaderPlugin = require('vue-loader/lib/plugin');\n\nconst cache = {};\nconst loaders = [\n  {\n    test: /\\.js$/,\n    loader: 'babel-loader',\n    exclude: /node_modules/\n  },\n  {\n    test: /\\.css$/,\n    use: [\n      'vue-style-loader',\n      'css-loader'\n    ]\n  },\n  {\n    test: /\\.vue$/,\n    loader: 'vue-loader',\n    query: {\n      preserveWhitespace: false\n    }\n  }\n];\nconst extensions = [\n  '.js', '.jsx', '.es6.js', '.msx'\n];\n\nmodule.exports = [{\n  mode: 'production',\n  cache: cache,\n  module: {\n    rules: loaders\n  },\n  entry: {\n    main: './src/main',\n  },\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: '[name].js',\n    sourceMapFilename: '[file].map',\n  },\n  resolve: {\n    modules: [\n      __dirname,\n      path.resolve(__dirname, 'src'),\n      'node_modules'\n    ],\n    extensions: extensions\n  },\n  plugins: [\n    new VueLoaderPlugin(),\n    new webpack.DefinePlugin({\n      'process.env': {\n        'NODE_ENV': JSON.stringify('production')\n      }\n    })\n  ]\n}];\n"
  },
  {
    "path": "scripts/bench/package.json",
    "content": "{\n  \"name\": \"rax-benchmark\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"src/index.js\",\n  \"scripts\": {\n    \"start\": \"node src/index.js\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"chalk\": \"^2.4.2\",\n    \"chrome-launcher\": \"latest\",\n    \"chromedriver\": \"latest\",\n    \"cli-table\": \"^0.3.1\",\n    \"debug\": \"^4.1.1\",\n    \"http-server\": \"^0.10.0\",\n    \"jstat\": \"^1.7.1\",\n    \"lighthouse\": \"^8.0.0\",\n    \"ramda\": \"^0.26.1\",\n    \"selenium-webdriver\": \"^4.0.0-alpha.1\",\n    \"yargs\": \"^13.2.2\"\n  }\n}\n"
  },
  {
    "path": "scripts/bench/src/benchmarks.js",
    "content": "const {\n  testTextContains,\n  testClassContains,\n  testElementLocatedByXpath,\n  testElementNotLocatedByXPath,\n  testElementLocatedById,\n  clickElementById,\n  clickElementByXPath,\n  getTextByXPath,\n} = require('./webdriverAccess');\n\nconst config = require('./config');\n\nconst SHORT_TIMEOUT = 20 * 1000;\n\nconst BenchmarkType = {\n  CPU: 'CPU',\n  MEM: 'MEM',\n  STARTUP: 'STARTUP'\n};\n\nconst BenchmarkTypeInfo = {\n  CPU: 'Duration in milliseconds ± 95% confidence interval (Slowdown = Duration / Fastest)',\n  MEMORY: 'Memory allocation in MBs ± 95% confidence interval',\n  STARTUP: 'Startup metrics (lighthouse with mobile simulation)'\n};\n\nexports.BenchmarkType = BenchmarkType;\nexports.BenchmarkTypeInfo = BenchmarkTypeInfo;\n\nclass Benchmark {\n  constructor(benchmarkInfo) {\n    this.benchmarkInfo = benchmarkInfo;\n    this.id = benchmarkInfo.id;\n    this.type = benchmarkInfo.type;\n    this.label = benchmarkInfo.label;\n    this.description = benchmarkInfo.description;\n    this.throttleCPU = benchmarkInfo.throttleCPU;\n  }\n  after(driver, framework) {\n    return null;\n  }\n  // Good fit for a single result creating Benchmark\n  resultKinds() {\n    return [this.benchmarkInfo];\n  }\n  extractResult(results, resultKind) {\n    return results;\n  }\n}\n\nconst benchRun = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '01_run1k',\n      label: 'create rows',\n      description: 'creating 1,000 rows',\n      title: 'creating 1,000 rows',\n      type: BenchmarkType.CPU\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'add', SHORT_TIMEOUT);\n  }\n  async run(driver) {\n    await clickElementById(driver, 'add');\n    await testElementLocatedByXpath(driver, '//tbody/tr[1000]/td[2]/a');\n  }\n}();\n\nconst benchReplaceAll = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '02_replace1k',\n      label: 'replace all rows',\n      description:\n        'updating all 1,000 rows (' + config.WARMUP_COUNT + ' warmup runs).',\n      title: 'updating all 1,000 rows',\n      type: BenchmarkType.CPU\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'run', SHORT_TIMEOUT);\n    for (let i = 0; i < config.WARMUP_COUNT; i++) {\n      await clickElementById(driver, 'run');\n      await testTextContains(\n        driver,\n        '//tbody/tr[1]/td[1]',\n        (i * 1000 + 1).toFixed()\n      );\n    }\n  }\n  async run(driver) {\n    await clickElementById(driver, 'run');\n    await testTextContains(driver, '//tbody/tr[1]/td[1]', '5001');\n  }\n}();\n\nconst benchUpdate = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '03_update10th1k_x16',\n      label: 'partial update',\n      description:\n        'updating every 10th row for 1,000 rows (3 warmup runs). 16x CPU slowdown.',\n      title: 'updating every 10th row',\n      type: BenchmarkType.CPU,\n      throttleCPU: 16\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'run', SHORT_TIMEOUT);\n    await clickElementById(driver, 'run');\n    await testElementLocatedByXpath(driver, '//tbody/tr[1000]/td[2]/a');\n    for (let i = 0; i < 3; i++) {\n      await clickElementById(driver, 'update');\n      await testTextContains(\n        driver,\n        '//tbody/tr[991]/td[2]/a',\n        ' !!!'.repeat(i + 1)\n      );\n    }\n  }\n  async run(driver) {\n    await clickElementById(driver, 'update');\n    await testTextContains(\n      driver,\n      '//tbody/tr[991]/td[2]/a',\n      ' !!!'.repeat(3 + 1)\n    );\n  }\n}();\n\nconst benchSelect = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '04_select1k',\n      label: 'select row',\n      description:\n        'highlighting a selected row. (' +\n        config.WARMUP_COUNT +\n        ' warmup runs). 16x CPU slowdown.',\n      title: 'select one row',\n      type: BenchmarkType.CPU,\n      throttleCPU: 16\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'run', SHORT_TIMEOUT);\n    await clickElementById(driver, 'run');\n    await testElementLocatedByXpath(driver, '//tbody/tr[1]/td[2]/a');\n    for (let i = 0; i <= config.WARMUP_COUNT; i++) {\n      await clickElementByXPath(driver, `//tbody/tr[${i + 1}]/td[2]/a`);\n    }\n  }\n  async run(driver) {\n    await clickElementByXPath(driver, '//tbody/tr[2]/td[2]/a');\n    await testClassContains(driver, '//tbody/tr[2]', 'danger');\n  }\n}();\n\nconst benchSwapRows = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '05_swap1k',\n      label: 'swap rows',\n      description:\n        'swap 2 rows for table with 1,000 rows. (' +\n        config.WARMUP_COUNT +\n        ' warmup runs). 4x CPU slowdown.',\n      title: 'swap 2 rows',\n      type: BenchmarkType.CPU,\n      throttleCPU: 4\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'run', SHORT_TIMEOUT);\n    await clickElementById(driver, 'run');\n    await testElementLocatedByXpath(driver, '//tbody/tr[1]/td[2]/a');\n    for (let i = 0; i <= config.WARMUP_COUNT; i++) {\n      let text = await getTextByXPath(driver, '//tbody/tr[2]/td[2]/a');\n      await clickElementById(driver, 'swaprows');\n      await testTextContains(driver, '//tbody/tr[999]/td[2]/a', text);\n    }\n  }\n  async run(driver) {\n    let text = await getTextByXPath(driver, '//tbody/tr[2]/td[2]/a');\n    await clickElementById(driver, 'swaprows');\n    await testTextContains(driver, '//tbody/tr[999]/td[2]/a', text);\n  }\n}();\n\nconst benchRemove = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '06_remove-one-1k',\n      label: 'remove row',\n      description:\n        'removing one row. (' + config.WARMUP_COUNT + ' warmup runs).',\n      title: 'removing one row',\n      type: BenchmarkType.CPU\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'run', SHORT_TIMEOUT);\n    await clickElementById(driver, 'run');\n    await testElementLocatedByXpath(driver, '//tbody/tr[1]/td[2]/a');\n    for (let i = 0; i < config.WARMUP_COUNT; i++) {\n      await testTextContains(\n        driver,\n        `//tbody/tr[${config.WARMUP_COUNT - i + 4}]/td[1]`,\n        (config.WARMUP_COUNT - i + 4).toString()\n      );\n      await clickElementByXPath(\n        driver,\n        `//tbody/tr[${config.WARMUP_COUNT - i + 4}]/td[3]/a/span[1]`\n      );\n      await testTextContains(\n        driver,\n        `//tbody/tr[${config.WARMUP_COUNT - i + 4}]/td[1]`,\n        '10'\n      );\n    }\n    await testTextContains(driver, '//tbody/tr[5]/td[1]', '10');\n    await testTextContains(driver, '//tbody/tr[4]/td[1]', '4');\n  }\n  async run(driver) {\n    await clickElementByXPath(driver, '//tbody/tr[4]/td[3]/a/span[1]');\n    await testTextContains(driver, '//tbody/tr[4]/td[1]', '10');\n  }\n}();\n\nconst benchRunBig = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '07_create10k',\n      label: 'create many rows',\n      description: 'creating 10,000 rows',\n      title: 'creating 10,000 rows',\n      type: BenchmarkType.CPU\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'runlots', SHORT_TIMEOUT);\n  }\n  async run(driver) {\n    await clickElementById(driver, 'runlots');\n    await testElementLocatedByXpath(driver, '//tbody/tr[10000]/td[2]/a');\n  }\n}();\n\nconst benchAppendToManyRows = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '08_create1k-after1k_x2',\n      label: 'append rows to large table',\n      description: 'appending 1,000 to a table of 10,000 rows. 2x CPU slowdown',\n      title: 'appending 1,000 rows',\n      type: BenchmarkType.CPU,\n      throttleCPU: 2\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'run', SHORT_TIMEOUT);\n    await clickElementById(driver, 'run');\n    await testElementLocatedByXpath(driver, '//tbody/tr[1000]/td[2]/a');\n  }\n  async run(driver) {\n    await clickElementById(driver, 'add');\n    await testElementLocatedByXpath(driver, '//tbody/tr[1100]/td[2]/a');\n  }\n}();\n\nconst benchClear = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '09_clear1k_x8',\n      label: 'clear rows',\n      description: 'clearing a table with 1,000 rows. 8x CPU slowdown',\n      title: 'clearing a table with 1,000 rows',\n      type: BenchmarkType.CPU,\n      throttleCPU: 8\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'run', SHORT_TIMEOUT);\n    await clickElementById(driver, 'run');\n    await testElementLocatedByXpath(driver, '//tbody/tr[1000]/td[2]/a');\n  }\n  async run(driver) {\n    await clickElementById(driver, 'clear');\n    await testElementNotLocatedByXPath(driver, '//tbody/tr[1]');\n  }\n}();\n\nconst benchReadyMemory = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '21_ready-memory',\n      label: 'ready memory',\n      description: 'Memory usage after page load.',\n      title: 'Memory usage after page load',\n      type: BenchmarkType.MEM\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'add', SHORT_TIMEOUT);\n  }\n  async run(driver) {\n    await testElementNotLocatedByXPath(driver, '//tbody/tr[1]');\n  }\n  async after(driver, framework) {\n    await clickElementById(driver, 'run');\n    await testElementLocatedByXpath(driver, '//tbody/tr[1]/td[2]/a');\n  }\n}();\n\nconst benchRunMemory = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '22_run-memory',\n      label: 'run memory',\n      description: 'Memory usage after adding 1000 rows.',\n      title: 'Memory usage after adding 1000 rows',\n      type: BenchmarkType.MEM\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'add', SHORT_TIMEOUT);\n  }\n  async run(driver) {\n    await clickElementById(driver, 'run');\n    await testElementLocatedByXpath(driver, '//tbody/tr[1]/td[2]/a');\n  }\n}();\n\nconst benchUpdate5Memory = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '23_update5-memory',\n      label: 'update eatch 10th row for 1k rows (5 cycles)',\n      description: 'Memory usage after clicking update every 10th row 5 times',\n      title: 'update every 10th row 5 times',\n      type: BenchmarkType.MEM\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'add', SHORT_TIMEOUT);\n  }\n  async run(driver) {\n    await clickElementById(driver, 'run');\n    for (let i = 0; i < 5; i++) {\n      await clickElementById(driver, 'update');\n      await testTextContains(driver, '//tbody/tr[1]/td[2]/a', ' !!!'.repeat(i));\n    }\n  }\n}();\n\nconst benchReplace5Memory = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '24_run5-memory',\n      label: 'replace 1k rows (5 cycles) ',\n      description: 'Memory usage after clicking create 1000 rows 5 times',\n      title: 'replace 1k rows 5 cycles',\n      type: BenchmarkType.MEM\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'add', SHORT_TIMEOUT);\n  }\n  async run(driver) {\n    for (let i = 0; i < 5; i++) {\n      await clickElementById(driver, 'run');\n      await testTextContains(\n        driver,\n        '//tbody/tr[1000]/td[1]',\n        (1000 * (i + 1)).toFixed()\n      );\n    }\n  }\n}();\n\nconst benchCreateClear5Memory = new class extends Benchmark {\n  constructor() {\n    super({\n      id: '25_run-clear-memory',\n      label: 'creating/clearing 1k rows (5 cycles)',\n      description: 'Memory usage after creating and clearing 1000 rows 5 times',\n      title: 'creating/clearing 1k rows 5 cycles',\n      type: BenchmarkType.MEM\n    });\n  }\n  async init(driver) {\n    await testElementLocatedById(driver, 'add', SHORT_TIMEOUT);\n  }\n  async run(driver) {\n    for (let i = 0; i < 5; i++) {\n      await clickElementById(driver, 'run');\n      await testTextContains(\n        driver,\n        '//tbody/tr[1000]/td[1]',\n        (1000 * (i + 1)).toFixed()\n      );\n      await clickElementById(driver, 'clear');\n      await testElementNotLocatedByXPath(driver, '//tbody/tr[1000]/td[1]');\n    }\n  }\n}();\n\nconst benchStartupConsistentlyInteractive = {\n  id: '31_startup-ci',\n  label: 'consistently interactive',\n  description:\n    'a pessimistic TTI - when the CPU and network are both definitely very idle. (no more CPU tasks over 50ms)',\n  type: BenchmarkType.STARTUP,\n  property: 'TimeToConsistentlyInteractive'\n};\n\nconst benchStartupBootup = {\n  id: '32_startup-bt',\n  label: 'script bootup time',\n  description:\n    \"the total ms required to parse/compile/evaluate all the page's scripts\",\n  type: BenchmarkType.STARTUP,\n  property: 'ScriptBootUpTtime'\n};\n\nconst benchStartupMainThreadWorkCost = {\n  id: '33_startup-mainthreadcost',\n  label: 'main thread work cost',\n  description:\n    'total amount of time spent doing work on the main thread. includes style/layout/etc.',\n  type: BenchmarkType.STARTUP,\n  property: 'MainThreadWorkCost'\n};\n\nconst benchStartupTotalBytes = {\n  id: '34_startup-totalbytes',\n  label: 'total kilobyte weight',\n  description:\n    'network transfer cost (post-compression) of all the resources loaded into the page.',\n  type: BenchmarkType.STARTUP,\n  property: 'TotalKiloByteWeight'\n};\n\nclass BenchStartup extends Benchmark {\n  constructor() {\n    super({\n      id: '30_startup',\n      label: 'startup time',\n      description: 'Time for loading, parsing and starting up',\n      type: BenchmarkType.STARTUP\n    });\n  }\n  async init(driver) {\n    await driver.get(`http://localhost:${config.PORT}/`);\n  }\n\n  async run(driver, framework) {\n    await driver.get(`http://localhost:${config.PORT}/${framework.uri}/`);\n    await testElementLocatedById(driver, 'run', SHORT_TIMEOUT);\n    return driver.sleep(config.STARTUP_SLEEP_DURATION);\n  }\n\n  extractResult(results, resultKind) {\n    return results.reduce((a, v) => {\n      a.push(v[resultKind.property]);\n      return a;\n    }, new Array());\n  }\n\n  resultKinds() {\n    return [\n      benchStartupConsistentlyInteractive,\n      benchStartupBootup,\n      benchStartupMainThreadWorkCost,\n      benchStartupTotalBytes\n    ];\n  }\n}\n\nconst benchStartup = new BenchStartup();\n\nexports.benchmarks = [\n  benchRun,\n  benchReplaceAll,\n  benchUpdate,\n  benchSelect,\n  benchSwapRows,\n  benchRemove,\n  benchRunBig,\n  benchAppendToManyRows,\n  benchClear,\n  benchReadyMemory,\n  benchRunMemory,\n  benchUpdate5Memory,\n  benchReplace5Memory,\n  benchCreateClear5Memory,\n  benchStartup\n];\n"
  },
  {
    "path": "scripts/bench/src/build.js",
    "content": "\nconst exec = require('child_process').exec;\nconst { join } = require('path');\n\nfunction executeCommand(command) {\n  return new Promise(_resolve =>\n    exec(command, error => {\n      if (!error) {\n        _resolve();\n      } else {\n        console.error(error);\n        process.exit(1);\n      }\n    })\n  );\n}\n\nasync function buildBundles(framework) {\n  const frameworkPath = join(__dirname, `../frameworks/${framework}`);\n\n  console.log(`building ${framework} in directory ${frameworkPath}`);\n  console.log();\n  console.log('running npm install && npm run build-prod');\n  console.log();\n\n  return await executeCommand(\n    `cd ${frameworkPath} && rm -rf node_modules && rm -rf dist && npm install && npm run build-prod`\n  );\n}\n\nmodule.exports = {\n  buildBundles\n};"
  },
  {
    "path": "scripts/bench/src/common.js",
    "content": "const path = require('path');\nconst fs = require('fs');\nconst os = require('os');\n\nfunction loadFrameworkVersionInformation(frameworks) {\n  const results = {};\n\n  frameworks.map((framework) => {\n    results[framework] = {\n      name: framework\n    };\n\n    if (framework === 'rax-local') {\n      results[framework].version = 'local';\n      return;\n    }\n\n    const frameworkPath = path.resolve(__dirname, `../frameworks/${framework}`);\n    const packageJSONPath = path.resolve(frameworkPath, 'package.json');\n    const packageLockJSONPath = path.resolve(frameworkPath, 'package-lock.json');\n\n    if (fs.existsSync(packageLockJSONPath)) {\n      const packageLock = JSON.parse(fs.readFileSync(packageLockJSONPath, 'utf8'));\n\n      if (packageLock.dependencies[framework]) {\n        results[framework].version = packageLock.dependencies[framework].version;\n      } else if (fs.existsSync(packageJSONPath)) {\n        const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf8'));\n\n        if (packageJSON.dependencies && packageJSON.dependencies[framework]) {\n          results[framework].version = packageJSON.dependencies[framework];\n        }\n      }\n    }\n  });\n\n  return results;\n}\n\nfunction getOSInformation() {\n  return {\n    platform: os.platform() + ' ' + os.release(),\n    cpu: os.cpus()[0].model,\n    'system memory': os.totalmem() / ( 1024 * 1024 * 1024 ) + 'GB',\n  };\n}\n\nmodule.exports = {\n  loadFrameworkVersionInformation,\n  getOSInformation\n};"
  },
  {
    "path": "scripts/bench/src/config.js",
    "content": "const config = {\n  PORT: 8080,\n  REPEAT_RUN: 3,\n  REPEAT_RUN_STARTUP: 4,\n  DROP_WORST_RUN: 0,\n  WARMUP_COUNT: 5,\n  TIMEOUT: 60 * 1000,\n  LOG_PROGRESS: false,\n  LOG_DETAILS: false,\n  LOG_DEBUG: false,\n  LOG_TIMELINE: false,\n  EXIT_ON_ERROR: false,\n  STARTUP_DURATION_FROM_EVENTLOG: true,\n  STARTUP_SLEEP_DURATION: 1000,\n  FORK_CHROMEDRIVER: true\n};\n\nmodule.exports = config;\n\n"
  },
  {
    "path": "scripts/bench/src/fomart.js",
    "content": "const { BenchmarkTypeInfo } = require('./benchmarks');\n\n/**\nconst results = {\n  \"CPU\": {\n    \"benchmarks\": {\n      \"01_run1k\": {\n        \"rax\": {\n          \"min\": 23,\n        },\n        \"preact\": {\n          \"min\": 22,\n        }\n      },\n      \"02_replace1k\": {}\n    },\n    \"mean\": \"1.20\"\n  }\n}\n*/\nmodule.exports = function(data, frameworks) {\n  const results = {};\n\n  Object.keys(data).map(framework => {\n    const benchmarks = data[framework];\n\n    benchmarks.map((item) => {\n      const {\n        type,\n        benchmark\n      } = item;\n\n      if (!results[type]) {\n        results[type] = {\n          benchmarks: {},\n          mean: {},\n          info: BenchmarkTypeInfo[type.toUpperCase()]\n        };\n      }\n\n      const benchmarksResults = results[type].benchmarks;\n\n      if (!benchmarksResults[benchmark]) {\n        benchmarksResults[benchmark] = {};\n      }\n\n      benchmarksResults[benchmark][framework] = item;\n    });\n  });\n\n  Object.keys(results).map(type => {\n    const resultsForType = results[type];\n\n    // compute factor for each benchmark\n    Object.keys(resultsForType.benchmarks).map(benchmark => {\n      const benchmarkResults = resultsForType.benchmarks[benchmark];\n\n      let min = frameworks.reduce((min, framework) => {\n        return benchmarkResults[framework] ? Math.min(min, benchmarkResults[framework].mean) : min;\n      }, Number.POSITIVE_INFINITY);\n\n      frameworks.map((framework) => {\n        const result = benchmarkResults[framework];\n        if (result) {\n          result.factor = (result.mean / min).toFixed(2);\n          result.deviation = (result.standardDeviation || 0) / result.mean * 100.0;\n        }\n      });\n    });\n\n    // compute geometric mean for each framwork\n    frameworks.map(framework => {\n      const resultsForFramework = Object.keys(resultsForType.benchmarks).map(benchmark => {\n        const benchmarkResults = resultsForType.benchmarks[benchmark];\n        return benchmarkResults[framework];\n      });\n      const mean = computeGeometricMean(resultsForFramework);\n      results[type].mean[framework] = mean;\n    });\n  });\n\n  return results;\n};\n\n// https://en.wikipedia.org/wiki/Geometric_mean\nfunction computeGeometricMean(resultsForFramework) {\n  let count = 0.0;\n  let gMean = resultsForFramework.reduce((gMean, r) => {\n    if (r) {\n      count++;\n      gMean *= r.factor;\n    }\n    return gMean;\n  }, 1.0);\n  let value = Math.pow(gMean, 1 / count).toFixed(2);\n  return value;\n}"
  },
  {
    "path": "scripts/bench/src/index.js",
    "content": "'use strict';\nconst { join } = require('path');\nconst { readdirSync, statSync, writeFileSync, existsSync, mkdirSync, readFileSync } = require('fs');\nconst yargs = require('yargs');\nconst debug = require('debug');\nconst chalk = require('chalk');\n\nconst { benchmarks } = require('./benchmarks');\nconst { executeBenchmark } = require('./runner');\nconst config = require('./config');\nconst format = require('./fomart');\nconst print = require('./print');\nconst createHTTPServer = require('./server');\nconst { buildBundles } = require('./build');\n\nfunction getFrameworkNames() {\n  return readdirSync(join(__dirname, '../frameworks')).filter(file =>\n    statSync(join(__dirname, '../frameworks', file)).isDirectory()\n  );\n}\n\nasync function runBench(framework, benchmarks, local, skipBuild) {\n  const errors = [];\n  const warnings = [];\n  const data = [];\n\n  const resultFolder = './results';\n  const resultJSON = `${resultFolder}/${framework}.json`;\n\n  if (local && existsSync(resultJSON)) {\n    const data = JSON.parse(readFileSync(resultJSON, {\n      encoding: 'utf-8'\n    }));\n\n    return {\n      data,\n      errors,\n      warnings\n    };\n  }\n\n  if (!skipBuild) {\n    await buildBundles(framework);\n  }\n\n  for (let i = 0; i < benchmarks.length; i ++) {\n    const benchmark = benchmarks[i];\n\n    try {\n      const benchmarkOptions = {\n        port: config.PORT.toFixed(),\n        headless: args.headless,\n        chromeBinaryPath: args.chromeBinary,\n        numIterationsForAllBenchmarks: config.REPEAT_RUN,\n        numIterationsForStartupBenchmark: config.REPEAT_RUN_STARTUP\n      };\n\n      const results = await executeBenchmark(\n        framework,\n        benchmark,\n        benchmarkOptions\n      );\n\n      errors.splice(errors.length, 0, ...results.errors);\n      warnings.splice(warnings.length, 0, ...results.warnings);\n      data.splice(data.length, 0, ...results.results);\n    } catch (err) {\n      console.log(err);\n      console.log(\n        `Error executing benchmark ${framework} and benchmark ${\n          benchmark.id\n        }`\n      );\n    }\n  }\n\n  if (!existsSync(resultFolder)) {\n    mkdirSync(resultFolder);\n  }\n\n  writeFileSync(\n    resultJSON,\n    JSON.stringify(data, null, 2),\n    { encoding: 'utf8' }\n  );\n\n  return {\n    errors,\n    warnings,\n    data\n  };\n}\n\nasync function run(frameworkNames, benchmarkNames, local, skipBuild) {\n  const server = createHTTPServer();\n\n  const errors = [];\n  const warnings = [];\n  const data = {};\n\n  const frameworks = getFrameworkNames();\n\n  const runFrameworks = frameworks.filter(f =>\n    frameworkNames.some(name => f.indexOf(name) > -1)\n  );\n  const runBenchmarks = benchmarks.filter(b =>\n    benchmarkNames.some(name => b.id.toLowerCase().indexOf(name) > -1)\n  );\n\n  console.log('Frameworks that will be benchmarked', runFrameworks);\n  console.log('Benchmarks that will be run', runBenchmarks.map(b => b.id));\n  console.log();\n\n  for (let i = 0; i < runFrameworks.length; i++) {\n    const framework = runFrameworks[i];\n    const results = await runBench(framework, runBenchmarks, local, skipBuild);\n\n    errors.splice(errors.length, 0, ...results.errors);\n    warnings.splice(warnings.length, 0, ...results.warnings);\n    data[framework] = results.data;\n  }\n\n  server.close();\n\n  const allBenchmarks = {};\n  runBenchmarks.forEach((benchmark) => {\n    let r = benchmark.resultKinds ? benchmark.resultKinds() : [benchmark];\n    r.forEach(benchmarkInfo => {\n      allBenchmarks[benchmarkInfo.id] = benchmarkInfo;\n    });\n  });\n\n\n  debug('results')(data);\n\n  const formatedData = format(data, runFrameworks, allBenchmarks);\n\n  debug('formatedData')(formatedData);\n\n  print(formatedData, runFrameworks, allBenchmarks);\n\n  if (warnings.length > 0) {\n    console.log('================================');\n    console.log('The following warnings were logged:');\n    console.log('================================');\n    warnings.forEach(e => {\n      console.log(e);\n    });\n  }\n  if (errors.length > 0) {\n    console.log('================================');\n    console.log('The following benchmarks failed:');\n    console.log('================================');\n    errors.forEach(e => {\n      console.log('[' + e.imageFile + ']');\n      console.log(e.exception);\n      console.log();\n    });\n    throw 'Benchmarking failed with errors';\n  }\n}\n\nconst args = yargs(process.argv)\n  .usage(\n    '$0 [--framework Framework1 Framework2 ...] [--benchmark Benchmark1 Benchmark2 ...] [--count n] [--exitOnError]'\n  )\n  .help('help')\n  .default('check', 'false')\n  .default('fork', 'true')\n  .default('exitOnError', 'false')\n  .default('count', config.REPEAT_RUN)\n  .default('port', config.PORT)\n  .string('chromeBinary')\n  .string('chromeDriver')\n  .boolean('headless')\n  .boolean('skipBuild')\n  .boolean('local')\n  .array('framework')\n  .array('benchmark').argv;\n\nconfig.PORT = Number(args.port);\nconfig.REPEAT_RUN = Number(args.count);\nconfig.EXIT_ON_ERROR = args.exitOnError === 'true';\n\nconst runBenchmarks =\n  args.benchmark && args.benchmark.length > 0 ? args.benchmark : [''];\nconst runFrameworks =\n  args.framework && args.framework.length > 0 ? args.framework : [''];\n\ndebug('args')(args);\n\nif (args.help) {\n  yargs.showHelp();\n} else {\n  run(runFrameworks, runBenchmarks, args.local, args.skipBuild)\n    .then(_ => {\n      console.log();\n      console.log(chalk.green('successful run'));\n      console.log();\n    })\n    .catch(error => {\n      console.log(error);\n      console.log('run was not completely sucessful');\n    });\n}\n"
  },
  {
    "path": "scripts/bench/src/print.js",
    "content": "const Table = require('cli-table');\nconst chalk = require('chalk');\nconst { loadFrameworkVersionInformation, getOSInformation } = require('./common');\n\n\nconst TABLE_CONFIG = {\n  chars: {\n    top: '',\n    'top-mid': '',\n    'top-left': '',\n    'top-right': '',\n    bottom: '',\n    'bottom-mid': '',\n    'bottom-left': '',\n    'bottom-right': '',\n    left: '',\n    'left-mid': '',\n    mid: ' ',\n    'mid-mid': '',\n    right: '',\n    'right-mid': '',\n    middle: '│'\n  }\n};\n\nmodule.exports = function(data, frameworks, benchmarks) {\n  const osInformation = getOSInformation();\n\n  console.log();\n  console.log('The benchmark was run on:');\n  Object.keys(osInformation).map(info => {\n    console.log('   ' + info.toUpperCase() + ': ' + osInformation[info]);\n  });\n\n  const frameworksInfo = loadFrameworkVersionInformation(frameworks);\n  Object.keys(data).map(type => {\n    console.log();\n    console.log(chalk.green(data[type].info));\n    console.log();\n\n    const table = new Table(TABLE_CONFIG);\n\n    // header\n    const rowHeader = [chalk.white.bold('Name')];\n    frameworks.map(framework => {\n      const frameworkInfo = frameworksInfo[framework];\n      const title = frameworkInfo.version ? `${frameworkInfo.name}@${frameworkInfo.version}` : frameworkInfo.name;\n      rowHeader.push(chalk.white.bold(title));\n    });\n    table.push(rowHeader);\n\n    const benchmarksResult = data[type].benchmarks;\n\n    // benchmark results\n    Object.keys(benchmarksResult).map(benchmark => {\n      const result = benchmarksResult[benchmark];\n\n      const benchmarkInfo = benchmarks[benchmark];\n      const title = benchmarkInfo.title || benchmarkInfo.label;\n      const row = [chalk.gray(title)];\n\n      frameworks.map(framework => {\n        if (!result[framework]) {\n          row.push('-');\n        } else {\n          const mean = result[framework].mean.toFixed(2);\n          const factor = result[framework].factor;\n          if (result[framework].warning) {\n            row.push(`${mean} ${chalk.red('(' + factor + ')')}`);\n            return;\n          }\n\n          if (result[framework].factor > 1.5) {\n            row.push(`${mean} ${chalk.yellow('(' + factor + ')')}`);\n            return;\n          }\n\n          row.push(`${mean} ${chalk.gray('(' + factor + ')')}`);\n        }\n      });\n\n      table.push(row);\n    });\n\n    // geometric mean\n    const meanResult = data[type].mean;\n    const row = [chalk.gray('slowdown geometric mean')];\n    frameworks.map(framework => {\n      const result = meanResult[framework];\n      if (result > 1.5) {\n        row.push(`${chalk.yellow(result)}`);\n        return;\n      }\n\n      row.push(result);\n    });\n\n    table.push(row);\n\n    console.log(table.toString());\n  });\n};\n"
  },
  {
    "path": "scripts/bench/src/runner.js",
    "content": "'use strict';\n\nconst chrome = require('selenium-webdriver/chrome');\nconst selenium_webdriver = require('selenium-webdriver');\nconst lighthouse = require('lighthouse');\nconst chromeLauncher = require('chrome-launcher');\nconst fs = require('fs');\nconst path = require('path');\nconst R = require('ramda');\nconst jStat = require('jstat').jStat;\n\nconst { BenchmarkType } = require('./benchmarks');\nconst webdriverAccess = require('./webdriverAccess');\nconst config = require('./config');\n\nrequire('chromedriver');\n\nselenium_webdriver.promise.USE_PROMISE_MANAGER = false;\n\nfunction extractRelevantEvents(entries) {\n  let filteredEvents = [];\n  let protocolEvents = [];\n  entries.forEach(x => {\n    let e = JSON.parse(x.message).message;\n    if (config.LOG_DETAILS) console.log(JSON.stringify(e));\n    if (e.method === 'Tracing.dataCollected') {\n      protocolEvents.push(e);\n    }\n    if (\n      e.method &&\n      (e.method.startsWith('Page') || e.method.startsWith('Network'))\n    ) {\n      protocolEvents.push(e);\n    } else if (e.params.name === 'EventDispatch') {\n      if (e.params.args.data.type === 'click') {\n        if (config.LOG_TIMELINE)\n          console.log('CLICK ', JSON.stringify(e));\n        filteredEvents.push({\n          type: 'click',\n          ts: +e.params.ts,\n          dur: +e.params.dur,\n          end: +e.params.ts + e.params.dur\n        });\n      }\n    } else if (\n      e.params.name === 'TimeStamp' &&\n      (e.params.args.data.message === 'afterBenchmark' ||\n        e.params.args.data.message === 'finishedBenchmark' ||\n        e.params.args.data.message === 'runBenchmark' ||\n        e.params.args.data.message === 'initBenchmark')\n    ) {\n      filteredEvents.push({\n        type: e.params.args.data.message,\n        ts: +e.params.ts,\n        dur: 0,\n        end: +e.params.ts\n      });\n      if (config.LOG_TIMELINE)\n        console.log('TIMESTAMP ', JSON.stringify(e));\n    } else if (e.params.name === 'navigationStart') {\n      filteredEvents.push({\n        type: 'navigationStart',\n        ts: +e.params.ts,\n        dur: 0,\n        end: +e.params.ts\n      });\n      if (config.LOG_TIMELINE)\n        console.log('NAVIGATION START ', JSON.stringify(e));\n    } else if (e.params.name === 'Paint') {\n      if (config.LOG_TIMELINE)\n        console.log('PAINT ', JSON.stringify(e));\n      filteredEvents.push({\n        type: 'paint',\n        ts: +e.params.ts,\n        dur: +e.params.dur,\n        end: +e.params.ts + e.params.dur,\n        evt: JSON.stringify(e)\n      });\n    } else if (e.params.name === 'MajorGC' && e.params.args.usedHeapSizeAfter) {\n      filteredEvents.push({\n        type: 'gc',\n        ts: +e.params.ts,\n        end: +e.params.ts,\n        mem: Number(e.params.args.usedHeapSizeAfter) / 1024 / 1024\n      });\n      if (config.LOG_TIMELINE) console.log('GC ', JSON.stringify(e));\n    }\n  });\n  return { filteredEvents, protocolEvents };\n}\n\nasync function fetchEventsFromPerformanceLog(driver) {\n  let timingResults = [];\n  let protocolResults = [];\n  let entries = [];\n  do {\n    entries = await driver\n      .manage()\n      .logs()\n      .get(selenium_webdriver.logging.Type.PERFORMANCE);\n    const { filteredEvents, protocolEvents } = extractRelevantEvents(entries);\n    timingResults = timingResults.concat(filteredEvents);\n    protocolResults = protocolResults.concat(protocolEvents);\n  } while (entries.length > 0);\n  return { timingResults, protocolResults };\n}\n\nfunction type_eq(requiredType) {\n  return e => e.type === requiredType;\n}\n\nfunction type_neq(requiredType) {\n  return e => e.type !== requiredType;\n}\n\nfunction asString(res) {\n  return res.reduce((old, cur) => old + '\\n' + JSON.stringify(cur), '');\n}\n\nfunction extractRawValue(results, id) {\n  let audits = results.audits;\n  if (!audits) return null;\n  let audit_with_id = audits[id];\n  if (typeof audit_with_id === 'undefined') return null;\n  if (typeof audit_with_id.numericValue === 'undefined') return null;\n  return audit_with_id.numericValue;\n}\n\nfunction rmDir(dirPath) {\n  try {\n    var files = fs.readdirSync(dirPath);\n  } catch (e) {\n    return;\n  }\n  if (files.length > 0)\n    for (var i = 0; i < files.length; i++) {\n      var filePath = path.join(dirPath, files[i]);\n      if (fs.statSync(filePath).isFile()) fs.unlinkSync(filePath);\n      else rmDir(filePath);\n    }\n  fs.rmdirSync(dirPath);\n}\n\nasync function runLighthouse(framework, benchmarkOptions) {\n  const opts = {\n    chromeFlags: [\n      '--headless',\n      '--no-sandbox',\n      '--no-first-run',\n      '--enable-automation',\n      '--disable-infobars',\n      '--disable-background-networking',\n      '--disable-background-timer-throttling',\n      '--disable-cache',\n      '--disable-translate',\n      '--disable-sync',\n      '--disable-extensions',\n      '--disable-default-apps',\n      '--window-size=1200,800'\n    ],\n    onlyCategories: ['performance'],\n    port: ''\n  };\n\n  try {\n    if (fs.existsSync('prefs')) rmDir('prefs');\n    fs.mkdirSync('prefs');\n    fs.mkdirSync('prefs/Default');\n    fs.copyFileSync('chromePreferences.json', 'prefs/Default/Preferences');\n\n    let options = {\n      chromeFlags: opts.chromeFlags,\n      logLevel: 'info',\n      userDataDir: 'prefs'\n    };\n    if (benchmarkOptions.chromeBinaryPath)\n      options.chromePath = benchmarkOptions.chromeBinaryPath;\n    let chrome = await chromeLauncher.launch(options);\n    opts.port = chrome.port;\n\n    let results = await lighthouse(\n      `http://localhost:${benchmarkOptions.port}/frameworks/${framework}/`,\n      opts,\n      null\n    );\n    await chrome.kill();\n    let LighthouseData = {\n      TimeToConsistentlyInteractive: extractRawValue(\n        results.lhr,\n        'interactive'\n      ),\n      ScriptBootUpTtime: Math.max(\n        16,\n        extractRawValue(results.lhr, 'bootup-time')\n      ),\n      MainThreadWorkCost: extractRawValue(\n        results.lhr,\n        'mainthread-work-breakdown'\n      ),\n      TotalKiloByteWeight:\n        extractRawValue(results.lhr, 'total-byte-weight') / 1024.0\n    };\n    return LighthouseData;\n  } catch (error) {\n    console.log('error running lighthouse', error);\n    throw error;\n  }\n}\n\nasync function computeResultsCPU(\n  driver,\n  benchmarkOptions,\n  framework,\n  benchmark,\n  warnings\n) {\n  let entriesBrowser = await driver\n    .manage()\n    .logs()\n    .get(selenium_webdriver.logging.Type.BROWSER);\n  if (config.LOG_DEBUG) console.log('browser entries', entriesBrowser);\n  const perfLogEvents = await fetchEventsFromPerformanceLog(driver);\n  let filteredEvents = perfLogEvents.timingResults;\n  if (config.LOG_DEBUG)\n    console.log('filteredEvents ', asString(filteredEvents));\n  let remaining = R.dropWhile(type_eq('initBenchmark'))(filteredEvents);\n  let results = [];\n  while (remaining.length > 0) {\n    let evts = R.splitWhen(type_eq('finishedBenchmark'))(remaining);\n    if (R.find(type_neq('runBenchmark'))(evts[0]) && evts[1].length > 0) {\n      let eventsDuringBenchmark = R.dropWhile(type_neq('runBenchmark'))(\n        evts[0]\n      );\n      if (config.LOG_DEBUG)\n        console.log('eventsDuringBenchmark ', eventsDuringBenchmark);\n      let clicks = R.filter(type_eq('click'))(eventsDuringBenchmark);\n      if (clicks.length !== 1) {\n        console.log(\n          'exactly one click event is expected',\n          eventsDuringBenchmark\n        );\n        throw 'exactly one click event is expected';\n      }\n      let eventsAfterClick = R.dropWhile(type_neq('click'))(\n        eventsDuringBenchmark\n      );\n      if (config.LOG_DEBUG)\n        console.log('eventsAfterClick', eventsAfterClick);\n      let paints = R.filter(type_eq('paint'))(eventsAfterClick);\n      if (paints.length == 0) {\n        console.log(\n          'at least one paint event is expected after the click event',\n          eventsAfterClick\n        );\n        throw 'at least one paint event is expected after the click event';\n      }\n      console.log('# of paint events ', paints.length);\n      if (paints.length > 2) {\n        warnings.push(\n          `For framework ${framework} and benchmark ${\n            benchmark.id\n          } the number of paint calls is higher than expected. There were ${\n            paints.length\n          } paints though at most 2 are expected. Please consider re-running and check the results`\n        );\n        console.log(\n          `For framework ${framework} and benchmark ${\n            benchmark.id\n          } the number of paint calls is higher than expected. There were ${\n            paints.length\n          } paints though at most 2 are expected. Please consider re-running and check the results`\n        );\n      }\n      paints.forEach(p => {\n        console.log('duration to paint ', (p.end - clicks[0].ts) / 1000.0);\n      });\n      let lastPaint = R.reduce(\n        (max, elem) => max.end > elem.end ? max : elem,\n        { end: 0 },\n        paints\n      );\n      let upperBoundForSoundnessCheck =\n        (R.last(eventsDuringBenchmark).end - eventsDuringBenchmark[0].ts) /\n        1000.0;\n      let duration = (lastPaint.end - clicks[0].ts) / 1000.0;\n\n      if (config.LOG_DEBUG) {\n        console.log(\n          '*** duration',\n          duration,\n          'upper bound ',\n          upperBoundForSoundnessCheck\n        );\n      }\n\n      if (duration < 0) {\n        console.log(\n          'soundness check failed. reported duration is less 0',\n          asString(eventsDuringBenchmark)\n        );\n        throw 'soundness check failed. reported duration is less 0';\n      }\n      if (duration > upperBoundForSoundnessCheck) {\n        console.log(\n          'soundness check failed. reported duration is bigger than whole benchmark duration',\n          asString(eventsDuringBenchmark)\n        );\n        throw 'soundness check failed. reported duration is bigger than whole benchmark duration';\n      }\n      results.push(duration);\n    }\n    remaining = R.drop(1, evts[1]);\n  }\n  if (results.length !== benchmarkOptions.numIterationsForAllBenchmarks) {\n    console.log(\n      `soundness check failed. number or results isn't ${\n        benchmarkOptions.numIterationsForAllBenchmarks\n      }`,\n      results,\n      asString(filteredEvents)\n    );\n    throw `soundness check failed. number or results isn't ${\n      benchmarkOptions.numIterationsForAllBenchmarks\n    }`;\n  }\n  return results;\n}\n\nasync function computeResultsMEM(\n  driver,\n  benchmarkOptions,\n  framework,\n  benchmark,\n  warnings\n) {\n  let entriesBrowser = await driver\n    .manage()\n    .logs()\n    .get(selenium_webdriver.logging.Type.BROWSER);\n  if (config.LOG_DEBUG) console.log('browser entries', entriesBrowser);\n  let filteredEvents = (await fetchEventsFromPerformanceLog(driver))\n    .timingResults;\n  if (config.LOG_DEBUG) console.log('filteredEvents ', filteredEvents);\n  let remaining = R.dropWhile(type_eq('initBenchmark'))(filteredEvents);\n  let results = [];\n  while (remaining.length > 0) {\n    let evts = R.splitWhen(type_eq('finishedBenchmark'))(remaining);\n    if (R.find(type_neq('runBenchmark'))(evts[0]) && evts[1].length > 0) {\n      let eventsDuringBenchmark = R.dropWhile(type_neq('runBenchmark'))(\n        evts[0]\n      );\n      if (config.LOG_DEBUG)\n        console.log('eventsDuringBenchmark ', eventsDuringBenchmark);\n      let gcs = R.filter(type_eq('gc'))(eventsDuringBenchmark);\n      let mem = R.last(gcs).mem;\n      console.log('*** memory', mem);\n      results.push(mem);\n    }\n    remaining = R.drop(1, evts[1]);\n  }\n  if (results.length !== benchmarkOptions.numIterationsForAllBenchmarks) {\n    console.log(\n      `soundness check failed. number or results isn't ${\n        benchmarkOptions.numIterationsForAllBenchmarks\n      }`,\n      results,\n      asString(filteredEvents)\n    );\n    throw `soundness check failed. number or results isn't ${\n      benchmarkOptions.numIterationsForAllBenchmarks\n    }`;\n  }\n  return results;\n}\n\nfunction buildDriver(benchmarkOptions) {\n  let args = [\n    '--js-flags=--expose-gc',\n    '--enable-precise-memory-info',\n    '--no-first-run',\n    '--disable-background-networking',\n    '--disable-background-timer-throttling',\n    '--disable-cache',\n    '--disable-translate',\n    '--disable-sync',\n    '--disable-extensions',\n    '--disable-default-apps',\n    '--window-size=1200,800'\n  ];\n\n  if (benchmarkOptions.headless) {\n    args.push('--headless');\n    args.push('--disable-gpu'); // https://bugs.chromium.org/p/chromium/issues/detail?id=737678\n    args.push('--no-sandbox');\n  }\n\n  let caps = new selenium_webdriver.Capabilities({\n    browserName: 'chrome',\n    platform: 'ANY',\n    version: 'stable',\n    'goog:chromeOptions': {\n      args: args,\n      'perfLoggingPrefs': {\n        'enableNetwork': true,\n        'enablePage': true,\n        'traceCategories': 'devtools.timeline,blink.user_timing'\n      },\n      'excludeSwitches': [ 'enable-automation' ]\n    },\n    'goog:loggingPrefs': {\n      'browser': 'ALL',\n      'performance': 'ALL'\n    }\n  });\n  // port probing fails sometimes on windows, the following driver construction avoids probing:\n  let service = new chrome.ServiceBuilder().setPort(benchmarkOptions.chromePort).build();\n  var driver = chrome.Driver.createSession(caps, service);\n\n  return driver;\n}\n\nasync function forceGC(framework, driver) {\n  if (framework.startsWith('angular-v4')) {\n    // workaround for window.gc for angular 4 - closure rewrites windows.gc\");\n    await driver.executeScript('window.Angular4PreservedGC();');\n  } else {\n    for (let i = 0; i < 5; i++) {\n      await driver.executeScript('window.gc();');\n    }\n  }\n}\n\nasync function runBenchmark(driver, benchmark, framework) {\n  await benchmark.run(driver, framework);\n  if (config.LOG_PROGRESS)\n    console.log('after run ', benchmark.id, benchmark.type, framework);\n  if (benchmark.type === BenchmarkType.MEM) {\n    await forceGC(framework, driver);\n  }\n}\n\nasync function afterBenchmark(driver, benchmark, framework) {\n  if (benchmark.after) {\n    await benchmark.after(driver, framework);\n    if (config.LOG_PROGRESS)\n      console.log(\n        'after benchmark ',\n        benchmark.id,\n        benchmark.type,\n        framework.name\n      );\n  }\n}\n\nasync function initBenchmark(driver, benchmark, framework) {\n  await benchmark.init(driver, framework);\n  if (config.LOG_PROGRESS)\n    console.log(\n      'after initialized ',\n      benchmark.id,\n      benchmark.type,\n      framework.name\n    );\n  if (benchmark.type === BenchmarkType.MEM) {\n    await forceGC(framework, driver);\n  }\n}\n\nfunction formatResult(res, dir) {\n  let benchmark = res.benchmark;\n  let framework = res.framework;\n  let keyed = res.framework.keyed;\n  let type = null;\n\n  const results = [];\n\n  switch (benchmark.type) {\n    case BenchmarkType.CPU:\n      type = 'cpu';\n      break;\n    case BenchmarkType.MEM:\n      type = 'memory';\n      break;\n    case BenchmarkType.STARTUP:\n      type = 'startup';\n      break;\n  }\n  for (let resultKind of benchmark.resultKinds()) {\n    let data = benchmark.extractResult(res.results, resultKind);\n    let s = jStat(data);\n    console.log(\n      `result ${framework} ${resultKind.id} min ${s.min()} max ${s.max()} mean ${s.mean()} median ${s.median()} stddev ${s.stdev(\n        true\n      )}`\n    );\n    let result = {\n      framework: res.framework,\n      keyed: keyed,\n      benchmark: resultKind.id,\n      type: type,\n      min: s.min(),\n      max: s.max(),\n      mean: s.mean(),\n      median: s.median(),\n      geometricMean: s.geomean(),\n      standardDeviation: s.stdev(true),\n      values: data\n    };\n\n    results.push(result);\n  }\n\n  return results;\n}\n\nasync function registerError(driver, framework, benchmark, error) {\n  let fileName = 'error-' + framework + '-' + benchmark.id + '.png';\n  console.error('Benchmark failed', error);\n  let image = await driver.takeScreenshot();\n  console.error(`Writing screenshot ${fileName}`);\n  fs.writeFileSync(fileName, image, { encoding: 'base64' });\n  return { imageFile: fileName, exception: error };\n}\nconst wait = (delay = 1000) => new Promise(res => setTimeout(res, delay));\n\nasync function runMemOrCPUBenchmark(framework, benchmark, benchmarkOptions) {\n  let errors = [];\n  let warnings = [];\n  let data = [];\n  console.log('benchmarking ', framework, benchmark.id);\n  let driver = buildDriver(benchmarkOptions);\n  try {\n    for (let i = 0; i < benchmarkOptions.numIterationsForAllBenchmarks; i++) {\n      try {\n        webdriverAccess.setUseShadowRoot(framework.useShadowRoot);\n        await driver.get(\n          `http://localhost:${benchmarkOptions.port}/frameworks/${framework}/`\n        );\n        // await (driver as any).sendDevToolsCommand('Network.enable');\n        // await (driver as any).sendDevToolsCommand('Network.emulateNetworkConditions', {\n        //     offline: false,\n        //     latency: 200, // ms\n        //     downloadThroughput: 780 * 1024 / 8, // 780 kb/s\n        //     uploadThroughput: 330 * 1024 / 8, // 330 kb/s\n        // });\n        await driver.executeScript(\"console.timeStamp('initBenchmark')\");\n        await initBenchmark(driver, benchmark, framework);\n        if (benchmark.throttleCPU) {\n          console.log('CPU slowdown', benchmark.throttleCPU);\n          await driver.sendDevToolsCommand('Emulation.setCPUThrottlingRate', {\n            rate: benchmark.throttleCPU\n          });\n        }\n        await driver.executeScript(\"console.timeStamp('runBenchmark')\");\n        await runBenchmark(driver, benchmark, framework);\n        if (benchmark.throttleCPU) {\n          console.log('resetting CPU slowdown');\n          await driver.sendDevToolsCommand('Emulation.setCPUThrottlingRate', {\n            rate: 1\n          });\n        }\n        await driver.executeScript(\"console.timeStamp('finishedBenchmark')\");\n        await afterBenchmark(driver, benchmark, framework);\n        await driver.executeScript(\"console.timeStamp('afterBenchmark')\");\n      } catch (e) {\n        errors.push({\n          imageFile: `${framework}-${benchmark.id}`,\n          exception: e\n        });\n        throw e;\n      }\n    }\n    let results =\n      benchmark.type === BenchmarkType.CPU\n        ? await computeResultsCPU(\n          driver,\n          benchmarkOptions,\n          framework,\n          benchmark,\n          warnings\n        )\n        : await computeResultsMEM(\n          driver,\n          benchmarkOptions,\n          framework,\n          benchmark,\n          warnings\n        );\n    data = await formatResult(\n      { framework: framework, results: results, benchmark: benchmark },\n      benchmarkOptions.outputDirectory\n    );\n    console.log('QUIT');\n    console.log();\n    await driver.close();\n    await driver.quit();\n  } catch (e) {\n    console.log('ERROR:', e);\n    await driver.close();\n    await driver.quit();\n    if (config.EXIT_ON_ERROR) {\n      throw 'Benchmarking failed';\n    }\n  }\n\n  return { errors, warnings, results: data };\n}\n\nasync function runStartupBenchmark(framework, benchmark, benchmarkOptions) {\n  console.log('benchmarking startup', framework, benchmark.id);\n\n  let errors = [];\n  let results = [];\n  for (let i = 0; i < benchmarkOptions.numIterationsForStartupBenchmark; i++) {\n    try {\n      results.push(await runLighthouse(framework, benchmarkOptions));\n    } catch (error) {\n      errors.push({ imageFile: null, exception: error });\n      throw error;\n    }\n  }\n  const formatedResults = await formatResult(\n    { framework: framework, results: results, benchmark: benchmark },\n    benchmarkOptions.outputDirectory\n  );\n  return { errors, warnings: [], results: formatedResults };\n}\n\nasync function executeBenchmark(framework, benchmark, benchmarkOptions) {\n  let result;\n  if (benchmark.type == BenchmarkType.STARTUP) {\n    result = await runStartupBenchmark(\n      framework,\n      benchmark,\n      benchmarkOptions\n    );\n  } else {\n    result = await runMemOrCPUBenchmark(\n      framework,\n      benchmark,\n      benchmarkOptions\n    );\n  }\n\n  return result;\n}\n\nexports.executeBenchmark = executeBenchmark;\n"
  },
  {
    "path": "scripts/bench/src/server.js",
    "content": "const httpServer = require('http-server');\n\nfunction createHTTPServer() {\n  const server = httpServer.createServer({\n    robots: true,\n    cache: 'no-store',\n    headers: {\n      'Access-Control-Allow-Origin': '*',\n      'Access-Control-Allow-Credentials': 'true',\n    },\n  });\n  server.listen(8080);\n  return server;\n}\n\nmodule.exports = createHTTPServer;"
  },
  {
    "path": "scripts/bench/src/webdriverAccess.js",
    "content": "const { By, Condition } = require('selenium-webdriver');\nconst config = require('./config');\n\nlet useShadowRoot = false;\nfunction setUseShadowRoot(val) {\n  useShadowRoot = val;\n}\n\n// Fake findByXPath for simple XPath expressions to allow usage with shadow dom\nasync function findByXPath(node, path) {\n  const elems = await node.findElements(By.xpath(path));\n  if (elems.length) {\n    return elems[0];\n  }\n  return null;\n}\n\nfunction waitForCondition(driver) {\n  return async function(text, fn, timeout) {\n    return await driver.wait(new Condition(text, fn), timeout);\n  };\n}\n\n// driver.findElement(By.xpath(\"//tbody/tr[1]/td[1]\")).getText().then(...) can throw a stale element error:\n// thus we're using a safer way here:\nasync function testTextContains(driver, xpath, text, timeout = config.TIMEOUT) {\n  return waitForCondition(driver)(\n    `testTextContains ${xpath} ${text}`,\n    async function(driver) {\n      try {\n        let elem = await shadowRoot(driver);\n        elem = await findByXPath(elem, xpath);\n        if (elem == null) return false;\n        let v = await elem.getText();\n        return v && v.indexOf(text) > -1;\n      } catch (err) {\n        console.log(\n          'ignoring error in testTextContains for xpath = ' +\n            xpath +\n            ' text = ' +\n            text,\n          err.toString().split('\\n')[0]\n        );\n      }\n    },\n    timeout\n  );\n}\n\nfunction testTextNotContained(driver, xpath, text, timeout = config.TIMEOUT) {\n  return waitForCondition(driver)(\n    `testTextNotContained ${xpath} ${text}`,\n    async function(driver) {\n      try {\n        let elem = await shadowRoot(driver);\n        elem = await findByXPath(elem, xpath);\n        if (elem == null) return false;\n        let v = await elem.getText();\n        return v && v.indexOf(text) == -1;\n      } catch (err) {\n        console.log(\n          'ignoring error in testTextNotContained for xpath = ' +\n            xpath +\n            ' text = ' +\n            text,\n          err.toString().split('\\n')[0]\n        );\n      }\n    },\n    timeout\n  );\n}\n\nfunction testClassContains(driver, xpath, text, timeout = config.TIMEOUT) {\n  return waitForCondition(driver)(\n    `testClassContains ${xpath} ${text}`,\n    async function(driver) {\n      try {\n        let elem = await shadowRoot(driver);\n        elem = await findByXPath(elem, xpath);\n        if (elem == null) return false;\n        let v = await elem.getAttribute('class');\n        return v && v.indexOf(text) > -1;\n      } catch (err) {\n        console.log(\n          'ignoring error in testClassContains for xpath = ' +\n            xpath +\n            ' text = ' +\n            text,\n          err.toString().split('\\n')[0]\n        );\n      }\n    },\n    timeout\n  );\n}\n\nfunction testElementLocatedByXpath(driver, xpath, timeout = config.TIMEOUT) {\n  return waitForCondition(driver)(\n    `testElementLocatedByXpath ${xpath}`,\n    async function(driver) {\n      try {\n        let elem = await shadowRoot(driver);\n        elem = await findByXPath(elem, xpath);\n        return elem ? true : false;\n      } catch (err) {\n        console.log(\n          'ignoring error in testElementLocatedByXpath for xpath = ' + xpath,\n          err.toString()\n        );\n      }\n    },\n    timeout\n  );\n}\n\nfunction testElementNotLocatedByXPath(driver, xpath, timeout = config.TIMEOUT) {\n  return waitForCondition(driver)(\n    `testElementNotLocatedByXPath ${xpath}`,\n    async function(driver) {\n      try {\n        let elem = await shadowRoot(driver);\n        elem = await findByXPath(elem, xpath);\n        return elem ? false : true;\n      } catch (err) {\n        console.log(\n          'ignoring error in testElementNotLocatedByXPath for xpath = ' + xpath,\n          err.toString().split('\\n')[0]\n        );\n      }\n    },\n    timeout\n  );\n}\n\nfunction testElementLocatedById(driver, id, timeout = config.TIMEOUT) {\n  return waitForCondition(driver)(\n    `testElementLocatedById ${id}`,\n    async function(driver) {\n      try {\n        let elem = await shadowRoot(driver);\n        elem = await elem.findElement(By.id(id));\n        return true;\n      } catch (err) {\n        // console.log(\"ignoring error in testElementLocatedById for id = \"+id,err.toString().split(\"\\n\")[0]);\n      }\n    },\n    timeout\n  );\n}\n\nasync function retry(retryCount, driver, fun) {\n  for (let i = 0; i < retryCount; i++) {\n    try {\n      return fun(driver, i);\n    } catch (err) {\n      console.log('retry failed');\n    }\n  }\n}\n// Stale element prevention. For aurelia even after a testElementLocatedById clickElementById for the same id can fail\n// No idea how that can be explained\nfunction clickElementById(driver, id) {\n  return retry(5, driver, async function(driver) {\n    let elem = await shadowRoot(driver);\n    elem = await elem.findElement(By.id(id));\n    await elem.click();\n  });\n}\n\nfunction clickElementByXPath(driver, xpath) {\n  return retry(5, driver, async function(driver, count) {\n    if (count > 1 && config.LOG_DETAILS)\n      console.log('clickElementByXPath ', xpath, ' attempt #', count);\n    let elem = await shadowRoot(driver);\n    elem = await findByXPath(elem, xpath);\n    await elem.click();\n  });\n  // Stale element possible:\n  // return to(driver.findElement(By.xpath(xpath)).click());\n}\n\nasync function getTextByXPath(driver, xpath) {\n  return await retry(5, driver, async function(driver, count) {\n    if (count > 1 && config.LOG_DETAILS)\n      console.log('getTextByXPath ', xpath, ' attempt #', count);\n    let elem = await shadowRoot(driver);\n    elem = await findByXPath(elem, xpath);\n    return await elem.getText();\n  });\n}\n\nasync function shadowRoot(driver) {\n  return useShadowRoot\n    ? await driver.executeScript(\n      'return document.querySelector(\"main-element\").shadowRoot'\n    )\n    : await driver.findElement(By.tagName('body'));\n}\n\nmodule.exports = {\n  setUseShadowRoot,\n  testTextContains,\n  testTextNotContained,\n  testClassContains,\n  testElementLocatedByXpath,\n  testElementNotLocatedByXPath,\n  testElementLocatedById,\n  clickElementById,\n  clickElementByXPath,\n  getTextByXPath\n};\n"
  },
  {
    "path": "scripts/check-and-publish.js",
    "content": "/**\n * Scripts to check unpublished version and run publish\n */\nconst { existsSync, readdirSync, readFileSync } = require('fs');\nconst { join } = require('path');\nconst { spawnSync } = require('child_process');\nconst axios = require('axios');\nconst semver = require('semver');\n\nconst RETRY_LIMIT = 8;\nconst TIMEOUT = 5000;\n\nfunction checkVersion(folder, callback) {\n  const ret = []; // { name: 'foo', workDir, latest: 'x.x.x', local: 'x.x.x' }\n  if (existsSync(folder)) {\n    const packages = readdirSync(folder)\n      // ignore dot files.\n      .filter((filename) => filename[0] != '.');\n    console.log('[PUBLISH] Start check with following packages:');\n    console.log(packages.map(p => '- ' + p).join('\\n'));\n\n    let finishCount = 0;\n    function finish() {\n      finishCount++;\n      if (finishCount === packages.length) {\n        callback(ret);\n      }\n    }\n\n    for (let i = 0; i < packages.length; i++) {\n      const packageFolderName = packages[i];\n      const packageInfoPath = join(folder, packageFolderName, 'package.json');\n      if (existsSync(packageInfoPath)) {\n        const packageInfo = JSON.parse(readFileSync(packageInfoPath));\n        checkVersionExists(packageInfo.name, packageInfo.version).then(\n          exists => {\n            if (!exists) {\n              ret.push({\n                name: packageInfo.name,\n                workDir: join(folder, packageFolderName),\n                local: packageInfo.version,\n                tag: packageInfo.npmTag || (isPrerelease(packageInfo.version) ? 'beta' : 'latest')\n              });\n            }\n            finish();\n          },\n        );\n      } else {\n        finish();\n      }\n    }\n  } else {\n    callback(ret);\n  }\n}\n\n\nfunction checkVersionExists(pkg, version, retry = 0) {\n  return axios(\n    `http://registry.npmjs.com/${encodeURIComponent(pkg)}/${encodeURIComponent(\n      version,\n    )}`,\n    { timeout: TIMEOUT }\n  )\n    .then(res => res.status === 200)\n    .catch(err => {\n      if (err.response && err.response.status === 404 || retry >= RETRY_LIMIT) {\n        return false;\n      } else {\n        console.log(`Retry ${pkg}@${version} Time: ${retry + 1}`);\n        return checkVersionExists(pkg, version, retry + 1);\n      }\n    });\n}\n\nfunction publish(pkg, workDir, version, tag) {\n  console.log('[PUBLISH]', `${pkg}@${version}`);\n\n  // npm publish\n  spawnSync('npm', [\n    'publish',\n    '--tag=' + tag,\n    // use default registry\n  ], {\n    stdio: 'inherit',\n    cwd: workDir,\n  });\n}\n\nfunction isPrerelease(v) {\n  const semVer = semver.parse(v);\n  if (semVer === null) return false;\n  return semVer.prerelease.length > 0;\n}\n\nfunction checkVersionAndPublish() {\n  checkVersion(join(__dirname, '../packages'), ret => {\n    console.log('');\n    if (ret.length === 0) {\n      console.log('[PUBLISH] No diff with all packages.');\n    } else {\n      console.log('[PUBLISH] Will publish following packages:');\n    }\n\n    for (let i = 0; i < ret.length; i++) {\n      const { local, tag, name } = ret[i];\n      console.log(`--- ${name}@${local} current tag: ${tag} ---`);\n    }\n\n    if (ret.length > 0) {\n      for (let i = 0; i < ret.length; i++) {\n        const { name, workDir, local, tag } = ret[i];\n        publish(name, workDir, local, tag);\n      }\n    }\n  });\n}\n\ncheckVersionAndPublish();\n"
  },
  {
    "path": "scripts/compile-packages.js",
    "content": "/**\n * script to build (transpile) files.\n * By default it transpiles all files for all packages and writes them\n * into `lib/` directory.\n * Non-js or files matching IGNORE_PATTERN will be copied without transpiling.\n *\n * Example:\n *  compile all packages: node ./scripts/compile-packages.js\n *  watch compile some packages: node ./scripts/compile-packages.js --watch --packages rax,rax-cli\n */\n'use strict';\n\nconst compile = require('./compile');\n\ncompile('packages');\ncompile('packages', true);\n"
  },
  {
    "path": "scripts/compile.js",
    "content": "/**\n * script to build (transpile) files.\n * By default it transpiles all files for all packages and writes them\n * into `lib/` directory.\n * Non-js or files matching IGNORE_PATTERN will be copied without transpiling.\n *\n * Example:\n *  compile all packages: node ./scripts/compile.js\n *  watch compile some packages: node ./scripts/compile.js --watch --packages rax,rax-cli\n */\n'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst spawnSync = require('child_process').spawnSync;\n\nconst babel = require('@babel/core');\nconst chalk = require('chalk');\nconst glob = require('glob');\nconst minimatch = require('minimatch');\nconst parseArgs = require('minimist');\nconst chokidar = require('chokidar');\n\nconst SRC_DIR = 'src';\nconst JS_FILES_PATTERN = '**/*.js';\nconst IGNORE_PATTERN = '**/{__tests__,__mocks__}/**';\n\n// Don't need compile packages\nconst IGNORE_COMPILE_PACKAGES = ['rax'];\n\nconst args = parseArgs(process.argv);\nconst customPackages = args.packages;\n\nconst getBabelConfig = require('./config/getBabelConfig');\n\nconst fixedWidth = str => {\n  const WIDTH = 80;\n  const strs = str.match(new RegExp(`(.{1,${WIDTH}})`, 'g'));\n  let lastString = strs[strs.length - 1];\n  if (lastString.length < WIDTH) {\n    lastString += Array(WIDTH - lastString.length).join(chalk.dim('.'));\n  }\n  return strs.slice(0, -1).concat(lastString).join('\\n');\n};\n\nfunction buildPackage(packagesDir, p, isBuildEs) {\n  const srcDir = path.resolve(p, SRC_DIR);\n  const pattern = path.resolve(srcDir, '**/*');\n  const files = glob.sync(pattern, {nodir: true});\n  const dirName = path.basename(p);\n\n  process.stdout.write(\n    fixedWidth(`${dirName}\\n`)\n  );\n\n  files.forEach(file => buildFile(packagesDir, file, isBuildEs));\n  process.stdout.write(`[  ${chalk.green('OK')}  ]\\n`);\n}\n\nfunction getPackages(packagesDir, customPackages) {\n  return fs.readdirSync(packagesDir)\n    .filter(file => !IGNORE_COMPILE_PACKAGES.includes(file)) // Exclude compile rax\n    .map(file => path.resolve(packagesDir, file))\n    .filter(f => {\n      if (customPackages) {\n        const packageName = path.relative(packagesDir, f).split(path.sep)[0];\n        return packageName.indexOf(customPackages) !== -1;\n      } else {\n        return true;\n      }\n    })\n    .filter(f => fs.lstatSync(path.resolve(f)).isDirectory());\n}\n\nfunction buildFile(packagesDir, file, isBuildEs) {\n  const BUILD_DIR = isBuildEs ? 'es' : 'lib';\n  const packageName = path.relative(packagesDir, file).split(path.sep)[0];\n  const packageSrcPath = path.resolve(packagesDir, packageName, SRC_DIR);\n  const packageBuildPath = path.resolve(packagesDir, packageName, BUILD_DIR);\n  const relativeToSrcPath = path.relative(packageSrcPath, file);\n  const destPath = path.resolve(packageBuildPath, relativeToSrcPath);\n\n  let babelOptions;\n  if (isBuildEs) {\n    babelOptions = getBabelConfig(true);\n  } else {\n    babelOptions = getBabelConfig();\n  }\n\n  spawnSync('mkdir', ['-p', path.dirname(destPath)]);\n  if (!minimatch(file, IGNORE_PATTERN)) {\n    if (!minimatch(file, JS_FILES_PATTERN)) {\n      fs.createReadStream(file).pipe(fs.createWriteStream(destPath));\n    } else {\n      const transformed = babel.transformFileSync(file, babelOptions).code;\n      spawnSync('mkdir', ['-p', path.dirname(destPath)]);\n      fs.writeFileSync(destPath, transformed);\n    }\n  }\n}\n\n// const packagesDir = path.resolve(__dirname, '../packages');\nmodule.exports = function compile(packagesName, isBuildEs) {\n  const packagesDir = path.resolve(__dirname, `../${packagesName}`);\n  const packages = getPackages(packagesDir, customPackages);\n\n  if (args.watch) {\n    // watch packages\n    const watchPackagesDir = packages.map(dir => path.resolve(dir, SRC_DIR));\n\n    console.log(chalk.green('watch packages compile', packages));\n\n    chokidar.watch(watchPackagesDir, {\n      ignored: IGNORE_PATTERN\n    }).on('change', (filePath) => {\n      const packageName = filePath.match( new RegExp(`\\/${packagesName}\\/([^\\/]*)`))[1];\n      const packagePath = path.resolve(__dirname, `../${packagesName}/`, packageName);\n      process.stdout.write(chalk.bold.inverse(`Compiling package ${packageName} \\n`));\n      try {\n        buildPackage(packagesDir, packagePath, isBuildEs);\n      } catch (e) {}\n      process.stdout.write('\\n');\n    });\n  } else {\n    process.stdout.write(chalk.bold.inverse('Compiling packages\\n'));\n    packages.forEach((v) => {\n      buildPackage(packagesDir, v, isBuildEs);\n    });\n    process.stdout.write('\\n');\n  }\n};\n"
  },
  {
    "path": "scripts/config/getBabelConfig.js",
    "content": "const babelMerge = require('babel-merge');\nconst babelConfig = require('../../babel.config')();\n\nmodule.exports = function(ignoreModule) {\n  const envOpt = {\n    loose: true,\n  };\n\n  if (ignoreModule) {\n    envOpt.modules = false;\n  }\n\n  return babelMerge(babelConfig, {\n    presets: [\n      ['@babel/preset-env', envOpt],\n    ],\n    plugins: [\n      '@babel/transform-runtime'\n    ]\n  });\n};\n"
  },
  {
    "path": "scripts/dist-core.js",
    "content": "const { join } = require('path');\nconst { readFileSync, existsSync } = require('fs');\nconst { green } = require('chalk');\nconst rollup = require('rollup');\nconst { nodeResolve } = require('@rollup/plugin-node-resolve');\nconst commonjs = require('@rollup/plugin-commonjs');\nconst { babel } = require('@rollup/plugin-babel');\nconst { terser } = require('rollup-plugin-terser');\nconst replace = require('@rollup/plugin-replace');\nconst gzipSize = require('gzip-size');\n\nconst UMD = 'umd';\nconst ESM = 'esm';\nconst CJS = 'cjs';\n\nfunction getExtension(format) {\n  let ext = '.js';\n  switch (format) {\n    case 'umd': ext = '.umd.js';\n      break;\n    case 'esm': ext = '.mjs';\n      break;\n  }\n  return ext;\n}\n\n/**\n * Rollup build options\n * @param buildOptions - rollup build options.\n * @param {string} buildOptions.packageName - package name\n * @param {string} buildOptions.name - package export name, such as umd format: window.Rax\n * @param {string} buildOptions.entry package entry path\n * @param {string} buildOptions.outputPath package output path\n * @param {boolean} buildOptions.shouldMinify compress code or not\n * @param {string} buildOptions.format bundle format (cjs|esm|iife|umd)\n * @param {Array} buildOptions.external external dependencies list\n * @param {Object} buildOptions.replaceValues rollup replace plugin values\n */\nasync function build({\n  packageName,\n  name,\n  entry = 'src/index.js',\n  outputPath,\n  shouldMinify = false,\n  format = UMD,\n  external,\n  replaceValues,\n}) {\n  const input = `./packages/${packageName}/${entry}`;\n  const output = {\n    name,\n    exports: 'named',\n    sourcemap: 'hidden',\n    compact: false, // This will minify the wrapper code generated by rollup.\n    freeze: false,\n    strict: false,\n    esModule: format === ESM,\n  };\n\n  const terserOptions = {\n    compress: {\n      loops: false,\n      keep_fargs: false,\n      unsafe: true,\n      pure_getters: true\n    },\n  };\n\n  if (shouldMinify) {\n    // Apply mangle rules.\n    terserOptions.mangle = {\n      properties: {\n        regex: /^__/,\n      },\n    };\n  }\n\n  // For development\n  const bundle = await rollup.rollup({\n    input,\n    external,\n    plugins: [\n      nodeResolve(),\n      commonjs({\n        // style-unit for build while packages linked\n        // use /packages/ would get error and it seemed to be a rollup-plugin-commonjs bug\n        include: /node_modules|style-unit/\n      }),\n      babel({\n        babelHelpers: 'bundled',\n        exclude: 'node_modules/**', // only transpile our source code\n        presets: [\n          ['@babel/preset-env', {\n            modules: false,\n            loose: true,\n            targets: {\n              browsers: ['last 2 versions', 'IE >= 9']\n            }\n          }]\n        ]\n      }),\n      replace({\n        values: {\n          ...replaceValues,\n          'process.env.NODE_ENV': JSON.stringify(shouldMinify ? 'production' : 'development'),\n        },\n        preventAssignment: true,\n      }),\n      shouldMinify ? terser(terserOptions) : null,\n    ]\n  });\n\n  const ext = getExtension(format);\n\n  if (shouldMinify) {\n    const file = outputPath || `./packages/${packageName}/dist/${packageName}.min${ext}`;\n    await bundle.write({\n      ...output,\n      format,\n      file,\n    });\n\n    const size = gzipSize.fileSync(file, {\n      level: 6\n    });\n\n    console.log(file, `${green((size / 1024).toPrecision(8) + 'KiB')} (Gzipped)`);\n  } else {\n    await bundle.write({\n      ...output,\n      format,\n      file: outputPath || `./packages/${packageName}/dist/${packageName}${ext}`,\n    });\n  }\n}\n\nfunction buildCorePackages(options) {\n  build(options);\n  build({ ...options, shouldMinify: true });\n  build({ ...options, format: CJS });\n  build({ ...options, format: CJS, shouldMinify: true });\n  build({ ...options, format: ESM });\n  build({ ...options, format: ESM, shouldMinify: true });\n}\n\n// Get rax version\nfunction getRaxVersion() {\n  const packageJSONPath = join(process.cwd(), 'packages/rax/package.json');\n  if (!existsSync(packageJSONPath)) {\n    throw new Error('rax package.json is not exists!');\n  }\n  const packageData = JSON.parse(readFileSync(packageJSONPath, { encoding: 'utf-8' }));\n  return JSON.stringify(packageData.version);\n}\n\nconst raxVersion = getRaxVersion();\n\nbuildCorePackages({\n  packageName: 'rax',\n  name: 'Rax',\n  replaceValues: {\n    'process.env.RAX_VERSION': raxVersion\n  }\n});\nbuildCorePackages({\n  packageName: 'driver-dom',\n  name: 'DriverDom'\n});\nbuildCorePackages({\n  packageName: 'driver-weex',\n  name: 'DriverKraken'\n});\n\n// Build rax compat react version to rax/lib/compat/index.js\n// It needs external ../../index, which won't bundle rax into lib/compat/index.js\n// If bundle rax into lib/compat/index.js, it will exist multiple version rax in the project with rax and react are used together\nbuild({\n  packageName: 'rax',\n  name: 'Rax',\n  entry: 'src/compat/index.js',\n  outputPath: './packages/rax/lib/compat/index.js',\n  format: CJS,\n  external: ['rax', 'rax-children', 'rax-is-valid-element', 'rax-create-factory', 'rax-clone-element'],\n  replaceValues: { 'process.env.RAX_VERSION': raxVersion },\n});\n"
  },
  {
    "path": "scripts/jest/setupEnvironment.js",
    "content": "/* eslint-disable */\nglobal.__weex_require__ = require;\n"
  },
  {
    "path": "scripts/jest/setupTests.js",
    "content": "/* global jasmine */\nconst shouldIgnoreConsoleError = require('./shouldIgnoreConsoleError');\nconst util = require('util');\nconst chalk = require('chalk'); // eslint-disable-line import/no-extraneous-dependencies\n\nexpect.extend({\n  ...require('./toWarnDev')\n});\n\n\nconst env = jasmine.getEnv();\n\n['error', 'warn'].forEach(methodName => {\n  const unexpectedConsoleCallStacks = [];\n  const newMethod = function(format, ...args) {\n    // Ignore uncaught errors reported by jsdom\n    // and React addendums because they're too noisy.\n    if (methodName === 'error' && shouldIgnoreConsoleError(format, args)) {\n      return;\n    }\n\n    // Capture the call stack now so we can warn about it later.\n    // The call stack has helpful information for the test author.\n    // Don't throw yet though b'c it might be accidentally caught and suppressed.\n    const stack = new Error().stack;\n    unexpectedConsoleCallStacks.push([\n      stack.substr(stack.indexOf('\\n') + 1),\n      util.format(format, ...args),\n    ]);\n  };\n\n  console[methodName] = newMethod;\n\n  env.beforeEach(() => {\n    unexpectedConsoleCallStacks.length = 0;\n  });\n\n  env.afterEach(() => {\n    if (console[methodName] !== newMethod) {\n      throw new Error(\n        `Test did not tear down console.${methodName} mock properly.`\n      );\n    }\n\n    if (unexpectedConsoleCallStacks.length > 0) {\n      const messages = unexpectedConsoleCallStacks.map(\n        ([stack, message]) =>\n          `${chalk.red(message)}\\n` +\n          `${stack\n            .split('\\n')\n            .map(line => chalk.gray(line))\n            .join('\\n')}`\n      );\n\n      const message =\n        `Expected test not to call ${chalk.bold(\n          `console.${methodName}()`\n        )}.\\n\\n` +\n        'If the warning is expected, test for it explicitly by:\\n' +\n        `1. Using the ${chalk.bold('.toWarnDev()')} / ${chalk.bold(\n          '.toLowPriorityWarnDev()'\n        )} matchers, or...\\n`;\n\n      throw new Error(`${message}\\n\\n${messages.join('\\n\\n')}`);\n    }\n  });\n});\n"
  },
  {
    "path": "scripts/jest/shouldIgnoreConsoleError.js",
    "content": "// https://github.com/facebook/react/blob/master/scripts/jest/shouldIgnoreConsoleError.js\nmodule.exports = function shouldIgnoreConsoleError(format, args) {\n  if (process.env.NODE_ENV !== 'production') {\n    if (typeof format === 'string') {\n      if (format.indexOf('Error: Uncaught [') === 0) {\n        // This looks like an uncaught error from invokeGuardedCallback() wrapper\n        // in development that is reported by jsdom. Ignore because it's noisy.\n        return true;\n      }\n      if (format.indexOf('The above error occurred') === 0) {\n        // This looks like an error addendum from ReactFiberErrorLogger.\n        // Ignore it too.\n        return true;\n      }\n    }\n  } else {\n    if (\n      format != null &&\n      typeof format.message === 'string' &&\n      typeof format.stack === 'string' &&\n      args.length === 0\n    ) {\n      // In production, ReactFiberErrorLogger logs error objects directly.\n      // They are noisy too so we'll try to ignore them.\n      return true;\n    }\n    if (\n      format.indexOf(\n        'act(...) is not supported in production builds of React'\n      ) === 0\n    ) {\n      // We don't yet support act() for prod builds, and warn for it.\n      // But we'd like to use act() ourselves for prod builds.\n      // Let's ignore the warning and #yolo.\n      return true;\n    }\n  }\n  // Looks legit\n  return false;\n};\n"
  },
  {
    "path": "scripts/jest/styleMock.js",
    "content": "// https://jestjs.io/docs/en/webpack#handling-static-assets\n// For CSS Modules\nmodule.exports = {};\n"
  },
  {
    "path": "scripts/jest/toWarnDev.js",
    "content": "// https://github.com/facebook/react/blob/master/scripts/jest/matchers/toWarnDev.js\nconst jestDiff = require('jest-diff').default; // eslint-disable-line import/no-extraneous-dependencies\nconst util = require('util');\nconst shouldIgnoreConsoleError = require('./shouldIgnoreConsoleError');\n\nfunction normalizeCodeLocInfo(str) {\n  return str && str.replace(/at .+?:\\d+/g, 'at **');\n}\n\nconst createMatcherFor = consoleMethod =>\n  function matcher(callback, expectedMessages, options = {}) {\n    if (process.env.NODE_ENV !== 'production') {\n      // Warn about incorrect usage of matcher.\n      if (typeof expectedMessages === 'string') {\n        expectedMessages = [expectedMessages];\n      } else if (!Array.isArray(expectedMessages)) {\n        throw Error(\n          'toWarnDev() requires a parameter of type string or an array of strings ' +\n            `but was given ${typeof expectedMessages}.`\n        );\n      }\n      if (\n        options != null &&\n        (typeof options !== 'object' || Array.isArray(options))\n      ) {\n        throw new Error(\n          'toWarnDev() second argument, when present, should be an object. ' +\n            'Did you forget to wrap the messages into an array?'\n        );\n      }\n      if (arguments.length > 3) {\n        // `matcher` comes from Jest, so it's more than 2 in practice\n        throw new Error(\n          'toWarnDev() received more than two arguments. ' +\n            'Did you forget to wrap the messages into an array?'\n        );\n      }\n\n      const withoutStack = options.withoutStack;\n      const logAllErrors = options.logAllErrors;\n      const warningsWithoutComponentStack = [];\n      const warningsWithComponentStack = [];\n      const unexpectedWarnings = [];\n\n      let lastWarningWithMismatchingFormat = null;\n      let lastWarningWithExtraComponentStack = null;\n\n      // Catch errors thrown by the callback,\n      // But only rethrow them if all test expectations have been satisfied.\n      // Otherwise an Error in the callback can mask a failed expectation,\n      // and result in a test that passes when it shouldn't.\n      let caughtError;\n\n      const isLikelyAComponentStack = message =>\n        typeof message === 'string' && message.includes('\\n    in ');\n\n      const consoleSpy = (format, ...args) => {\n        // Ignore uncaught errors reported by jsdom\n        // and React addendums because they're too noisy.\n        if (\n          !logAllErrors &&\n          consoleMethod === 'error' &&\n          shouldIgnoreConsoleError(format, args)\n        ) {\n          return;\n        }\n\n        const message = util.format(format, ...args);\n        const normalizedMessage = normalizeCodeLocInfo(message);\n\n        // Remember if the number of %s interpolations\n        // doesn't match the number of arguments.\n        // We'll fail the test if it happens.\n        let argIndex = 0;\n        format.replace(/%s/g, () => argIndex++);\n        if (argIndex !== args.length) {\n          lastWarningWithMismatchingFormat = {\n            format,\n            args,\n            expectedArgCount: argIndex,\n          };\n        }\n\n        // Protect against accidentally passing a component stack\n        // to warning() which already injects the component stack.\n        if (\n          args.length >= 2 &&\n          isLikelyAComponentStack(args[args.length - 1]) &&\n          isLikelyAComponentStack(args[args.length - 2])\n        ) {\n          lastWarningWithExtraComponentStack = {\n            format,\n          };\n        }\n\n        for (let index = 0; index < expectedMessages.length; index++) {\n          const expectedMessage = expectedMessages[index];\n          if (\n            normalizedMessage === expectedMessage ||\n            normalizedMessage.includes(expectedMessage)\n          ) {\n            if (isLikelyAComponentStack(normalizedMessage)) {\n              warningsWithComponentStack.push(normalizedMessage);\n            } else {\n              warningsWithoutComponentStack.push(normalizedMessage);\n            }\n            expectedMessages.splice(index, 1);\n            return;\n          }\n        }\n\n        let errorMessage;\n        if (expectedMessages.length === 0) {\n          errorMessage =\n            'Unexpected warning recorded: ' +\n            this.utils.printReceived(normalizedMessage);\n        } else if (expectedMessages.length === 1) {\n          errorMessage =\n            'Unexpected warning recorded: ' +\n            jestDiff(expectedMessages[0], normalizedMessage);\n        } else {\n          errorMessage =\n            'Unexpected warning recorded: ' +\n            jestDiff(expectedMessages, [normalizedMessage]);\n        }\n\n        // Record the call stack for unexpected warnings.\n        // We don't throw an Error here though,\n        // Because it might be suppressed by ReactFiberScheduler.\n        unexpectedWarnings.push(new Error(errorMessage));\n      };\n\n      // TODO Decide whether we need to support nested toWarn* expectations.\n      // If we don't need it, add a check here to see if this is already our spy,\n      // And throw an error.\n      const originalMethod = console[consoleMethod];\n\n      // Avoid using Jest's built-in spy since it can't be removed.\n      console[consoleMethod] = consoleSpy;\n\n      try {\n        callback();\n      } catch (error) {\n        caughtError = error;\n      } finally {\n        // Restore the unspied method so that unexpected errors fail tests.\n        console[consoleMethod] = originalMethod;\n\n        // Any unexpected Errors thrown by the callback should fail the test.\n        // This should take precedence since unexpected errors could block warnings.\n        if (caughtError) {\n          throw caughtError;\n        }\n\n        // Any unexpected warnings should be treated as a failure.\n        if (unexpectedWarnings.length > 0) {\n          return {\n            message: () => unexpectedWarnings[0].stack,\n            pass: false,\n          };\n        }\n\n        // Any remaining messages indicate a failed expectations.\n        if (expectedMessages.length > 0) {\n          return {\n            message: () =>\n              `Expected warning was not recorded:\\n  ${this.utils.printReceived(\n                expectedMessages[0]\n              )}`,\n            pass: false,\n          };\n        }\n\n        if (typeof withoutStack === 'number') {\n          // We're expecting a particular number of warnings without stacks.\n          if (withoutStack !== warningsWithoutComponentStack.length) {\n            return {\n              message: () =>\n                `Expected ${withoutStack} warnings without a component stack but received ${\n                  warningsWithoutComponentStack.length\n                }:\\n` +\n                warningsWithoutComponentStack.map(warning =>\n                  this.utils.printReceived(warning)\n                ),\n              pass: false,\n            };\n          }\n        } else if (withoutStack === true) {\n          // We're expecting that all warnings won't have the stack.\n          // If some warnings have it, it's an error.\n          if (warningsWithComponentStack.length > 0) {\n            return {\n              message: () =>\n                `Received warning unexpectedly includes a component stack:\\n  ${this.utils.printReceived(\n                  warningsWithComponentStack[0]\n                )}\\nIf this warning intentionally includes the component stack, remove ` +\n                '{withoutStack: true} from the toWarnDev() call. If you have a mix of ' +\n                'warnings with and without stack in one toWarnDev() call, pass ' +\n                '{withoutStack: N} where N is the number of warnings without stacks.',\n              pass: false,\n            };\n          }\n        } else if (withoutStack === false || withoutStack === undefined) {\n          // We're expecting that all warnings *do* have the stack (default).\n          // If some warnings don't have it, it's an error.\n          if (warningsWithoutComponentStack.length > 0) {\n            return {\n              message: () =>\n                `Received warning unexpectedly does not include a component stack:\\n  ${this.utils.printReceived(\n                  warningsWithoutComponentStack[0]\n                )}\\nIf this warning intentionally omits the component stack, add ` +\n                '{withoutStack: true} to the toWarnDev() call.',\n              pass: false,\n            };\n          }\n        } else {\n          throw Error(\n            'The second argument for toWarnDev(), when specified, must be an object. It may have a ' +\n              'property called \"withoutStack\" whose value may be undefined, boolean, or a number. ' +\n              `Instead received ${typeof withoutStack}.`\n          );\n        }\n\n\n        if (lastWarningWithExtraComponentStack !== null) {\n          return {\n            message: () =>\n              `Received more than one component stack for a warning:\\n  ${this.utils.printReceived(\n                lastWarningWithExtraComponentStack.format\n              )}\\nDid you accidentally pass a stack to warning() as the last argument? ` +\n              'Don\\'t forget warning() already injects the component stack automatically.',\n            pass: false,\n          };\n        }\n\n        return {pass: true};\n      }\n    } else {\n      // Any uncaught errors or warnings should fail tests in production mode.\n      callback();\n\n      return {pass: true};\n    }\n  };\n\nmodule.exports = {\n  toLowPriorityWarnDev: createMatcherFor('warn'),\n  toWarnDev: createMatcherFor('error'),\n};\n"
  },
  {
    "path": "scripts/mapCoverage.js",
    "content": "/**\n * Because we have a build step, sometimes we can test files from both\n * `packages/jest-whatever/build/*` and `packages/jest-whatever/src/*`\n *\n * If we require file by its relative path like:\n *    // inside `jest-whatever/src/__tests__/index.js`\n *    require('../index.js'); // this will require `jest-whatever/src/index.js`\n *\n * But if we require it by a package name, this will go through node_modules\n * and lerna index.js link. So the actual file will be required from `build/`\n *    // inside another packages\n *    // this will go through lerna and require `jest-whatever/build/index.js\n *    require('jest-whatever')\n *\n * these files are identical (one is preprocessed, another is transformed on\n * the fly), but the coverage paths are different.\n * This script will map coverage results from both locations to one and\n * produce a full coverage report.\n */\n\nconst createReporter = require('istanbul-api').createReporter;\nconst coverage = require('../coverage/coverage-final.json');\nconst istanbulCoverage = require('istanbul-lib-coverage');\n\nconst map = istanbulCoverage.createCoverageMap();\nconst reporter = createReporter();\n\nconst mapFileCoverage = fileCoverage => {\n  fileCoverage.path = fileCoverage.path\n    .replace(/(.*packages\\/.*\\/)(lib)(\\/.*)/, '$1src$3');\n  return fileCoverage;\n};\n\nObject.keys(coverage).forEach(\n  filename => map.addFileCoverage(mapFileCoverage(coverage[filename]))\n);\n\nreporter.addAll(['json', 'lcov', 'text']);\nreporter.write(map);\n"
  },
  {
    "path": "scripts/validate-commit-msg.js",
    "content": "#!/usr/bin/env node\n\n/**\n * Git COMMIT-MSG hook for validating commit message\n * See https://docs.google.com/document/d/1rk04jEuGfk9kYzfqCuOlPTSJw3hEDZJTBN5E5f1SALo/edit\n *\n * Installation:\n * >> use ghooks, config in package.json\n */\n\n'use strict';\n\nvar fs = require('fs');\nvar util = require('util');\nvar resolve = require('path').resolve;\nvar findup = require('findup');\nvar semverRegex = require('semver-regex');\n\nvar config = getConfig();\nvar MAX_LENGTH = config.maxSubjectLength || 100;\nvar IGNORED = new RegExp(util.format('(^WIP)|(^v)|(^%s$)', semverRegex().source));\n\n// fixup! and squash! are part of Git, commits tagged with them are not intended to be merged, cf. https://git-scm.com/docs/git-commit\nvar PATTERN = /^((fixup! |squash! )?(\\w+)(?:\\(([^\\)\\s]+)\\))?: (.+))(?:\\n|$)/;\nvar MERGE_COMMIT_PATTERN = /^Merge /;\nvar error = function() {\n  // gitx does not display it\n  // http://gitx.lighthouseapp.com/projects/17830/tickets/294-feature-display-hook-error-message-when-hook-fails\n  // https://groups.google.com/group/gitx/browse_thread/thread/a03bcab60844b812\n  console[config.warnOnFail ? 'warn' : 'error']('Invalid commit message: ' + util.format.apply(null, arguments));\n  console.log('See our specific at:', 'https://github.com/alibaba/rax/.github/GIT_COMMIT_SPECIFIC.md');\n};\n\n\nvar validateMessage = function(raw) {\n  var types = config.types = config.types || 'conventional-commit-types';\n\n  // resolve types from a module\n  if (typeof types === 'string' && types !== '*') {\n    types = Object.keys(require(types).types);\n  }\n\n  var messageWithBody = (raw || '').split('\\n').filter(function(str) {\n    return str.indexOf('#') !== 0;\n  }).join('\\n');\n\n  var message = messageWithBody.split('\\n').shift();\n\n  if (message === '') {\n    console.log('Aborting commit due to empty commit message.');\n    return false;\n  }\n\n  var isValid = true;\n\n  if (MERGE_COMMIT_PATTERN.test(message)) {\n    console.log('Merge commit detected.');\n    return true;\n  }\n\n  if (IGNORED.test(message)) {\n    console.log('Commit message validation ignored.');\n    return true;\n  }\n\n  var match = PATTERN.exec(message);\n\n  if (!match) {\n    error('does not match \"<type>(<scope>): <subject>\" !');\n    isValid = false;\n  } else {\n    var firstLine = match[1];\n    var squashing = !!match[2];\n    var type = match[3];\n    var scope = match[4];\n    var subject = match[5];\n\n    var SUBJECT_PATTERN = new RegExp(config.subjectPattern || '.+');\n    var SUBJECT_PATTERN_ERROR_MSG = config.subjectPatternErrorMsg || 'subject does not match subject pattern!';\n\n    if (firstLine.length > MAX_LENGTH && !squashing) {\n      error('is longer than %d characters !', MAX_LENGTH);\n      isValid = false;\n    }\n\n    if (types !== '*' && types.indexOf(type) === -1) {\n      error('\"%s\" is not allowed type ! Valid types are: %s', type, types.join(', '));\n      isValid = false;\n    }\n\n    if (!SUBJECT_PATTERN.exec(subject)) {\n      error(SUBJECT_PATTERN_ERROR_MSG);\n      isValid = false;\n    }\n  }\n\n  // Some more ideas, do want anything like this ?\n  // - Validate the rest of the message (body, footer, BREAKING CHANGE annotations)\n  // - allow only specific scopes (eg. fix(docs) should not be allowed ?\n  // - auto correct the type to lower case ?\n  // - auto correct first letter of the subject to lower case ?\n  // - auto add empty line after subject ?\n  // - auto remove empty () ?\n  // - auto correct typos in type ?\n  // - store incorrect messages, so that we can learn\n\n  isValid = isValid || config.warnOnFail;\n\n  if (isValid) { // exit early and skip messaging logics\n    return true;\n  }\n\n  var argInHelp = config.helpMessage && config.helpMessage.indexOf('%s') !== -1;\n\n  if (argInHelp) {\n    console.log(config.helpMessage, messageWithBody);\n  } else if (message) {\n    console.log(message);\n  }\n\n  if (!argInHelp && config.helpMessage) {\n    console.log(config.helpMessage);\n  }\n\n  return false;\n};\n\n\n// publish for testing\nexports.validateMessage = validateMessage;\nexports.getGitFolder = getGitFolder;\nexports.config = config;\n\n// hacky start if not run by mocha :-D\n// istanbul ignore next\nif (process.argv.join('').indexOf('mocha') === -1) {\n  var commitMsgFile = process.argv[2] || getGitFolder() + '/COMMIT_EDITMSG';\n  var incorrectLogFile = commitMsgFile.replace('COMMIT_EDITMSG', 'logs/incorrect-commit-msgs');\n\n  var hasToString = function hasToString(x) {\n    return x && typeof x.toString === 'function';\n  };\n\n  fs.readFile(commitMsgFile, function(err, buffer) {\n    var msg = getCommitMessage(buffer);\n\n    if (!validateMessage(msg)) {\n      fs.appendFile(incorrectLogFile, msg + '\\n', function() {\n        process.exit(1);\n      });\n    } else {\n      process.exit(0);\n    }\n\n    function getCommitMessage(buffer) {\n      return hasToString(buffer) && buffer.toString();\n    }\n  });\n}\n\nfunction getConfig() {\n  var pkgFile = findup.sync(process.cwd(), 'package.json');\n  var pkg = JSON.parse(fs.readFileSync(resolve(pkgFile, 'package.json')));\n  return pkg && pkg.config && pkg.config['validate-commit-msg'] || {};\n}\n\nfunction getGitFolder() {\n  var gitDirLocation = './.git';\n  if (!fs.existsSync(gitDirLocation)) {\n    throw new Error('Cannot find file ' + gitDirLocation);\n  }\n\n  if (!fs.lstatSync(gitDirLocation).isDirectory()) {\n    var unparsedText = '' + fs.readFileSync(gitDirLocation);\n    gitDirLocation = unparsedText.substring('gitdir: '.length).trim();\n  }\n\n  if (!fs.existsSync(gitDirLocation)) {\n    throw new Error('Cannot find file ' + gitDirLocation);\n  }\n\n  return gitDirLocation;\n}\n"
  }
]